go-typst/docker-exec_test.go

185 lines
4.6 KiB
Go

// Copyright (c) 2025 David Vogel
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
package typst_test
import (
"bytes"
"image"
"os/exec"
"strconv"
"testing"
"github.com/Dadido3/go-typst"
)
func TestDockerExec(t *testing.T) {
// Just to ensure that there is no container running.
exec.Command("docker", "stop", "-t", "1", "typst-instance").Run()
exec.Command("docker", "rm", "typst-instance").Run()
if err := exec.Command("docker", "run", "--name", "typst-instance", "-v", "./test-files:/test-files", "-id", "123marvin123/typst").Run(); err != nil {
t.Fatalf("Failed to run Docker container: %v.", err)
}
t.Cleanup(func() {
exec.Command("docker", "stop", "-t", "1", "typst-instance").Run()
exec.Command("docker", "rm", "typst-instance").Run()
})
tests := []struct {
Name string
Function func(*testing.T)
}{
{"VersionString", dockerExec_VersionString},
{"Fonts", dockerExec_Fonts},
{"FontsWithOptions", dockerExec_FontsWithOptions},
{"FontsWithFontPaths", dockerExec_FontsWithFontPaths},
{"Compile", dockerExec_Compile},
{"CompileWithWorkingDir", dockerExec_CompileWithWorkingDir},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
t.Parallel()
test.Function(t)
})
}
}
func dockerExec_VersionString(t *testing.T) {
typstCaller := typst.DockerExec{
ContainerName: "typst-instance",
}
v, err := typstCaller.VersionString()
if err != nil {
t.Fatalf("Failed to get typst version: %v.", err)
}
t.Logf("VersionString: %s", v)
}
func dockerExec_Fonts(t *testing.T) {
typstCaller := typst.DockerExec{
ContainerName: "typst-instance",
}
result, err := typstCaller.Fonts(nil)
if err != nil {
t.Fatalf("Failed to get available fonts: %v.", err)
}
if len(result) < 4 {
t.Errorf("Unexpected number of detected fonts. Got %d, want >= %d.", len(result), 4)
}
}
func dockerExec_FontsWithOptions(t *testing.T) {
typstCaller := typst.DockerExec{
ContainerName: "typst-instance",
}
result, err := typstCaller.Fonts(&typst.OptionsFonts{IgnoreSystemFonts: true})
if err != nil {
t.Fatalf("Failed to get available fonts: %v.", err)
}
if len(result) != 4 {
t.Errorf("Unexpected number of detected fonts. Got %d, want %d.", len(result), 4)
}
}
func dockerExec_FontsWithFontPaths(t *testing.T) {
typstCaller := typst.DockerExec{
ContainerName: "typst-instance",
}
result, err := typstCaller.Fonts(&typst.OptionsFonts{IgnoreSystemFonts: true, FontPaths: []string{"/test-files"}})
if err != nil {
t.Fatalf("Failed to get available fonts: %v.", err)
}
if len(result) != 5 {
t.Errorf("Unexpected number of detected fonts. Got %d, want %d.", len(result), 5)
}
}
// Test basic compile functionality.
func dockerExec_Compile(t *testing.T) {
const inches = 1
const ppi = 144
typstCaller := typst.DockerExec{
ContainerName: "typst-instance",
}
r := bytes.NewBufferString(`#set page(width: ` + strconv.FormatInt(inches, 10) + `in, height: ` + strconv.FormatInt(inches, 10) + `in, margin: (x: 1mm, y: 1mm))
= Test
#lorem(5)`)
opts := typst.OptionsCompile{
Format: typst.OutputFormatPNG,
PPI: ppi,
}
var w bytes.Buffer
if err := typstCaller.Compile(r, &w, &opts); err != nil {
t.Fatalf("Failed to compile document: %v.", err)
}
imgConf, imgType, err := image.DecodeConfig(&w)
if err != nil {
t.Fatalf("Failed to decode image: %v.", err)
}
if imgType != "png" {
t.Fatalf("Resulting image is of type %q, expected %q.", imgType, "png")
}
if imgConf.Width != inches*ppi {
t.Fatalf("Resulting image width is %d, expected %d.", imgConf.Width, inches*ppi)
}
if imgConf.Height != inches*ppi {
t.Fatalf("Resulting image height is %d, expected %d.", imgConf.Height, inches*ppi)
}
}
// Test basic compile functionality with a given working directory.
func dockerExec_CompileWithWorkingDir(t *testing.T) {
typstCaller := typst.DockerExec{
ContainerName: "typst-instance",
}
r := bytes.NewBufferString(`#import "hello-world-template.typ": template
#show: doc => template()`)
var w bytes.Buffer
err := typstCaller.Compile(r, &w, &typst.OptionsCompile{Root: "/test-files"})
if err != nil {
t.Fatalf("Failed to compile document: %v.", err)
}
if w.Available() == 0 {
t.Errorf("No output was written.")
}
}
func TestDockerExec_EmptyContainerName(t *testing.T) {
typstCaller := typst.DockerExec{
ContainerName: "",
}
_, err := typstCaller.VersionString()
if err == nil {
t.Errorf("Expected error, but got nil.")
}
}
func TestDockerExec_NonRunningContainer(t *testing.T) {
typstCaller := typst.DockerExec{
ContainerName: "something-else",
}
_, err := typstCaller.VersionString()
if err == nil {
t.Errorf("Expected error, but got nil.")
}
}