feat(pdfengines): add PDF/UA (#714)

This commit is contained in:
Julien Neuhart
2023-11-05 20:14:36 +01:00
committed by GitHub
parent 9c3dfc78df
commit 143b7ce678
39 changed files with 1300 additions and 1013 deletions

View File

@@ -11,26 +11,26 @@ import (
"github.com/gotenberg/gotenberg/v7/pkg/gotenberg"
)
func TestPDFEngines_Descriptor(t *testing.T) {
descriptor := PDFEngines{}.Descriptor()
func TestPdfEngines_Descriptor(t *testing.T) {
descriptor := new(PdfEngines).Descriptor()
actual := reflect.TypeOf(descriptor.New())
expect := reflect.TypeOf(new(PDFEngines))
expect := reflect.TypeOf(new(PdfEngines))
if actual != expect {
t.Errorf("expected '%s' but got '%s'", expect, actual)
}
}
func TestPDFEngines_Provision(t *testing.T) {
tests := []struct {
name string
ctx *gotenberg.Context
expectPDFEngineNames []string
expectProvisionErr bool
func TestPdfEngines_Provision(t *testing.T) {
for _, tc := range []struct {
scenario string
ctx *gotenberg.Context
expectedPdfEngines []string
expectError bool
}{
{
name: "no selection from user",
scenario: "no selection from user",
ctx: func() *gotenberg.Context {
provider := &struct {
gotenberg.ModuleMock
@@ -48,7 +48,7 @@ func TestPDFEngines_Provision(t *testing.T) {
engine := &struct {
gotenberg.ModuleMock
gotenberg.ValidatorMock
gotenberg.PDFEngineMock
gotenberg.PdfEngineMock
}{}
engine.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return engine }}
@@ -59,7 +59,7 @@ func TestPDFEngines_Provision(t *testing.T) {
return gotenberg.NewContext(
gotenberg.ParsedFlags{
FlagSet: new(PDFEngines).Descriptor().FlagSet,
FlagSet: new(PdfEngines).Descriptor().FlagSet,
},
[]gotenberg.ModuleDescriptor{
provider.Descriptor(),
@@ -67,10 +67,11 @@ func TestPDFEngines_Provision(t *testing.T) {
},
)
}(),
expectPDFEngineNames: []string{"bar"},
expectedPdfEngines: []string{"bar"},
expectError: false,
},
{
name: "selection from user",
scenario: "selection from user",
ctx: func() *gotenberg.Context {
provider := &struct {
gotenberg.ModuleMock
@@ -88,7 +89,7 @@ func TestPDFEngines_Provision(t *testing.T) {
engine1 := &struct {
gotenberg.ModuleMock
gotenberg.ValidatorMock
gotenberg.PDFEngineMock
gotenberg.PdfEngineMock
}{}
engine1.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "a", New: func() gotenberg.Module { return engine1 }}
@@ -100,7 +101,7 @@ func TestPDFEngines_Provision(t *testing.T) {
engine2 := &struct {
gotenberg.ModuleMock
gotenberg.ValidatorMock
gotenberg.PDFEngineMock
gotenberg.PdfEngineMock
}{}
engine2.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "b", New: func() gotenberg.Module { return engine2 }}
@@ -109,10 +110,10 @@ func TestPDFEngines_Provision(t *testing.T) {
return nil
}
fs := new(PDFEngines).Descriptor().FlagSet
fs := new(PdfEngines).Descriptor().FlagSet
err := fs.Parse([]string{"--pdfengines-engines=b", "--pdfengines-engines=a"})
if err != nil {
t.Fatalf("expected no error from fs.Parse(), but got: %v", err)
t.Fatalf("expected no error but got: %v", err)
}
return gotenberg.NewContext(
@@ -126,10 +127,11 @@ func TestPDFEngines_Provision(t *testing.T) {
},
)
}(),
expectPDFEngineNames: []string{"b", "a"},
expectedPdfEngines: []string{"b", "a"},
expectError: false,
},
{
name: "user select deprecated unoconv-pdfengine",
scenario: "user select deprecated unoconv-pdfengine",
ctx: func() *gotenberg.Context {
provider := &struct {
gotenberg.ModuleMock
@@ -147,19 +149,19 @@ func TestPDFEngines_Provision(t *testing.T) {
engine := &struct {
gotenberg.ModuleMock
gotenberg.ValidatorMock
gotenberg.PDFEngineMock
gotenberg.PdfEngineMock
}{}
engine.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "api-pdfengine", New: func() gotenberg.Module { return engine }}
return gotenberg.ModuleDescriptor{ID: "libreoffice-pdfengine", New: func() gotenberg.Module { return engine }}
}
engine.ValidateMock = func() error {
return nil
}
fs := new(PDFEngines).Descriptor().FlagSet
fs := new(PdfEngines).Descriptor().FlagSet
err := fs.Parse([]string{"--pdfengines-engines=unoconv-pdfengine"})
if err != nil {
t.Fatalf("expected no error from fs.Parse(), but got: %v", err)
t.Fatalf("expected no error but got: %v", err)
}
return gotenberg.NewContext(
@@ -172,22 +174,23 @@ func TestPDFEngines_Provision(t *testing.T) {
},
)
}(),
expectPDFEngineNames: []string{"api-pdfengine"},
expectedPdfEngines: []string{"libreoffice-pdfengine"},
expectError: false,
},
{
name: "no logger provider",
scenario: "no logger provider",
ctx: func() *gotenberg.Context {
return gotenberg.NewContext(
gotenberg.ParsedFlags{
FlagSet: new(PDFEngines).Descriptor().FlagSet,
FlagSet: new(PdfEngines).Descriptor().FlagSet,
},
[]gotenberg.ModuleDescriptor{},
)
}(),
expectProvisionErr: true,
expectError: true,
},
{
name: "no logger from logger provider",
scenario: "no logger from logger provider",
ctx: func() *gotenberg.Context {
provider := &struct {
gotenberg.ModuleMock
@@ -204,17 +207,17 @@ func TestPDFEngines_Provision(t *testing.T) {
return gotenberg.NewContext(
gotenberg.ParsedFlags{
FlagSet: new(PDFEngines).Descriptor().FlagSet,
FlagSet: new(PdfEngines).Descriptor().FlagSet,
},
[]gotenberg.ModuleDescriptor{
provider.Descriptor(),
},
)
}(),
expectProvisionErr: true,
expectError: true,
},
{
name: "no valid PDF engines",
scenario: "no valid PDF engine",
ctx: func() *gotenberg.Context {
provider := &struct {
gotenberg.ModuleMock
@@ -232,7 +235,7 @@ func TestPDFEngines_Provision(t *testing.T) {
engine := &struct {
gotenberg.ModuleMock
gotenberg.ValidatorMock
gotenberg.PDFEngineMock
gotenberg.PdfEngineMock
}{}
engine.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return engine }}
@@ -243,7 +246,7 @@ func TestPDFEngines_Provision(t *testing.T) {
return gotenberg.NewContext(
gotenberg.ParsedFlags{
FlagSet: new(PDFEngines).Descriptor().FlagSet,
FlagSet: new(PdfEngines).Descriptor().FlagSet,
},
[]gotenberg.ModuleDescriptor{
provider.Descriptor(),
@@ -251,67 +254,66 @@ func TestPDFEngines_Provision(t *testing.T) {
},
)
}(),
expectProvisionErr: true,
expectError: true,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
mod := new(PDFEngines)
} {
t.Run(tc.scenario, func(t *testing.T) {
mod := new(PdfEngines)
err := mod.Provision(tc.ctx)
if tc.expectProvisionErr && err == nil {
t.Fatal("expected mod.Provision() error, but got none")
if !tc.expectError && err != nil {
t.Fatalf("expected no error but got: %v", err)
}
if !tc.expectProvisionErr && err != nil {
t.Fatalf("expected no error from mod.Provision(), but got: %v", err)
if tc.expectError && err == nil {
t.Fatal("expected error but got none")
}
if len(tc.expectPDFEngineNames) != len(mod.names) {
t.Errorf("expected %d names but got %d", len(tc.expectPDFEngineNames), len(mod.names))
if len(tc.expectedPdfEngines) != len(mod.names) {
t.Fatalf("expected %d names but got %d", len(tc.expectedPdfEngines), len(mod.names))
}
for index, name := range mod.names {
if name != tc.expectPDFEngineNames[index] {
t.Errorf("expected name at index %d to be %s, but got: %s", index, name, tc.expectPDFEngineNames[index])
if name != tc.expectedPdfEngines[index] {
t.Fatalf("expected scenario at index %d to be %s, but got: %s", index, name, tc.expectedPdfEngines[index])
}
}
})
}
}
func TestPDFEngines_Validate(t *testing.T) {
tests := []struct {
name string
names []string
engines []gotenberg.PDFEngine
expectValidateErr bool
func TestPdfEngines_Validate(t *testing.T) {
for _, tc := range []struct {
scenario string
names []string
engines []gotenberg.PdfEngine
expectError bool
}{
{
name: "existing PDF engine",
names: []string{"foo"},
engines: func() []gotenberg.PDFEngine {
scenario: "existing PDF engine",
names: []string{"foo"},
engines: func() []gotenberg.PdfEngine {
engine := &struct {
gotenberg.ModuleMock
gotenberg.PDFEngineMock
gotenberg.PdfEngineMock
}{}
engine.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return engine }}
}
return []gotenberg.PDFEngine{
return []gotenberg.PdfEngine{
engine,
}
}(),
expectError: false,
},
{
name: "non-existing bar PDF engine",
names: []string{"foo", "bar", "baz"},
engines: func() []gotenberg.PDFEngine {
scenario: "non-existing bar PDF engine",
names: []string{"foo", "bar", "baz"},
engines: func() []gotenberg.PdfEngine {
engine1 := &struct {
gotenberg.ModuleMock
gotenberg.PDFEngineMock
gotenberg.PdfEngineMock
}{}
engine1.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return engine1 }}
@@ -319,67 +321,65 @@ func TestPDFEngines_Validate(t *testing.T) {
engine2 := &struct {
gotenberg.ModuleMock
gotenberg.PDFEngineMock
gotenberg.PdfEngineMock
}{}
engine2.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "baz", New: func() gotenberg.Module { return engine2 }}
}
return []gotenberg.PDFEngine{
return []gotenberg.PdfEngine{
engine1,
engine2,
}
}(),
expectValidateErr: true,
expectError: true,
},
{
name: "no PDF engine",
expectValidateErr: true,
scenario: "no PDF engine",
expectError: true,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
mod := PDFEngines{
} {
t.Run(tc.scenario, func(t *testing.T) {
mod := PdfEngines{
names: tc.names,
engines: tc.engines,
}
err := mod.Validate()
if tc.expectValidateErr && err == nil {
t.Errorf("expected mod.Validate() error, but got none")
if !tc.expectError && err != nil {
t.Fatalf("expected no error but got: %v", err)
}
if !tc.expectValidateErr && err != nil {
t.Errorf("expected no error from mod.Validate(), but got: %v", err)
if tc.expectError && err == nil {
t.Fatal("expected error but got none")
}
})
}
}
func TestPDFEngines_SystemMessages(t *testing.T) {
mod := new(PDFEngines)
func TestPdfEngines_SystemMessages(t *testing.T) {
mod := new(PdfEngines)
mod.names = []string{"foo", "bar"}
messages := mod.SystemMessages()
if len(messages) != 1 {
t.Errorf("expected one and only one message from mod.SystemMessages(), but got %d", len(messages))
t.Errorf("expected one and only one message, but got %d", len(messages))
}
expect := strings.Join(mod.names[:], " ")
if messages[0] != expect {
t.Errorf("expected message '%s' from mod.SystemMessages(), but got '%s'", expect, messages[0])
t.Errorf("expected message '%s', but got '%s'", expect, messages[0])
}
}
func TestPDFEngines_PDFEngine(t *testing.T) {
mod := PDFEngines{
func TestPdfEngines_PdfEngine(t *testing.T) {
mod := PdfEngines{
names: []string{"foo", "bar"},
engines: func() []gotenberg.PDFEngine {
engines: func() []gotenberg.PdfEngine {
engine1 := &struct {
gotenberg.ModuleMock
gotenberg.PDFEngineMock
gotenberg.PdfEngineMock
}{}
engine1.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "foo", New: func() gotenberg.Module { return engine1 }}
@@ -387,57 +387,53 @@ func TestPDFEngines_PDFEngine(t *testing.T) {
engine2 := &struct {
gotenberg.ModuleMock
gotenberg.PDFEngineMock
gotenberg.PdfEngineMock
}{}
engine2.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return engine2 }}
}
return []gotenberg.PDFEngine{
return []gotenberg.PdfEngine{
engine1,
engine2,
}
}(),
}
_, err := mod.PDFEngine()
_, err := mod.PdfEngine()
if err != nil {
t.Errorf("expected no error from mod.PDFEngine, but got: %v", err)
t.Errorf("expected no error but got: %v", err)
}
}
func TestPDFEngines_Routes(t *testing.T) {
tests := []struct {
name string
mod PDFEngines
expectRoutesCount int
func TestPdfEngines_Routes(t *testing.T) {
for _, tc := range []struct {
scenario string
expectRoutes int
disableRoutes bool
}{
{
name: "route not disabled",
mod: PDFEngines{
engines: []gotenberg.PDFEngine{
&gotenberg.PDFEngineMock{},
},
},
expectRoutesCount: 2,
scenario: "routes not disabled",
expectRoutes: 2,
disableRoutes: false,
},
{
name: "route disabled",
mod: PDFEngines{
disableRoutes: true,
},
scenario: "routes disabled",
expectRoutes: 0,
disableRoutes: true,
},
}
} {
t.Run(tc.scenario, func(t *testing.T) {
mod := new(PdfEngines)
mod.disableRoutes = tc.disableRoutes
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
routes, err := tc.mod.Routes()
routes, err := mod.Routes()
if err != nil {
t.Fatalf("expected no error from mod.Routes(), but got: %v", err)
t.Fatalf("expected no error but got: %v", err)
}
if tc.expectRoutesCount != len(routes) {
t.Errorf("expected %d routes from mod.Routes(), but got %d", tc.expectRoutesCount, len(routes))
if tc.expectRoutes != len(routes) {
t.Errorf("expected %d routes but got %d", tc.expectRoutes, len(routes))
}
})
}