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

@@ -47,17 +47,17 @@ type Options struct {
Landscape bool
// PageRanges allows to select the pages to convert.
// TODO: should prefer a method form PDFEngine.
// TODO: should prefer a method form PdfEngine.
// Optional.
PageRanges string
// PdfFormat allows to convert the resulting PDF to PDF/A-1a, PDF/A-2b, or
// PDF/A-3b.
// PdfFormats allows to convert the resulting PDF to PDF/A-1a, PDF/A-2b,
// PDF/A-3b and PDF/UA.
// Optional.
PdfFormat string
PdfFormats gotenberg.PdfFormats
}
// Uno is an abstraction on top of Api.
// Uno is an abstraction on top of the Universal Network Objects API.
type Uno interface {
Pdf(ctx context.Context, logger *zap.Logger, inputPath, outputPath string, options Options) error
Extensions() []string
@@ -265,13 +265,13 @@ func (a *Api) Metrics() ([]gotenberg.Metric, error) {
func (a *Api) Checks() ([]health.CheckerOption, error) {
return []health.CheckerOption{
health.WithCheck(health.Check{
Name: "api",
Name: "libreoffice",
Check: func(_ context.Context) error {
if a.supervisor.Healthy() {
return nil
}
return errors.New("LibreOffice unhealthy")
return errors.New("LibreOffice is unhealthy")
},
}),
}, nil

View File

@@ -270,18 +270,26 @@ func (p *libreOfficeProcess) pdf(ctx context.Context, logger *zap.Logger, inputP
args = append(args, "--export", fmt.Sprintf("PageRange=%s", options.PageRanges))
}
switch options.PdfFormat {
switch options.PdfFormats.PdfA {
case "":
case gotenberg.FormatPDFA1a:
case gotenberg.PdfA1a:
args = append(args, "--export", "SelectPdfVersion=1")
case gotenberg.FormatPDFA2b:
case gotenberg.PdfA2b:
args = append(args, "--export", "SelectPdfVersion=2")
case gotenberg.FormatPDFA3b:
case gotenberg.PdfA3b:
args = append(args, "--export", "SelectPdfVersion=3")
default:
return ErrInvalidPdfFormat
}
if options.PdfFormats.PdfUa {
args = append(
args,
"--export", "EnableTextAccessForAccessibilityTools=true",
"--export", "UseTaggedPDF=true",
)
}
args = append(args, "--output", outputPath, inputPath)
cmd, err := gotenberg.CommandContext(ctx, logger, p.arguments.unoBinPath, args...)

View File

@@ -243,7 +243,7 @@ func TestLibreOfficeProcess_pdf(t *testing.T) {
return p
}(),
fs: gotenberg.NewFileSystem(),
options: Options{PdfFormat: "foo"},
options: Options{PdfFormats: gotenberg.PdfFormats{PdfA: "foo"}},
cancelledCtx: false,
start: false,
expectError: true,
@@ -417,7 +417,7 @@ func TestLibreOfficeProcess_pdf(t *testing.T) {
return fs
}(),
options: Options{PdfFormat: gotenberg.FormatPDFA1a},
options: Options{PdfFormats: gotenberg.PdfFormats{PdfA: gotenberg.PdfA1a}},
cancelledCtx: false,
start: true,
expectError: false,
@@ -446,7 +446,7 @@ func TestLibreOfficeProcess_pdf(t *testing.T) {
return fs
}(),
options: Options{PdfFormat: gotenberg.FormatPDFA2b},
options: Options{PdfFormats: gotenberg.PdfFormats{PdfA: gotenberg.PdfA2b}},
cancelledCtx: false,
start: true,
expectError: false,
@@ -475,7 +475,36 @@ func TestLibreOfficeProcess_pdf(t *testing.T) {
return fs
}(),
options: Options{PdfFormat: gotenberg.FormatPDFA3b},
options: Options{PdfFormats: gotenberg.PdfFormats{PdfA: gotenberg.PdfA3b}},
cancelledCtx: false,
start: true,
expectError: false,
},
{
scenario: "success (PDF/UA)",
libreOffice: newLibreOfficeProcess(
libreOfficeArguments{
binPath: os.Getenv("LIBREOFFICE_BIN_PATH"),
unoBinPath: os.Getenv("UNOCONV_BIN_PATH"),
startTimeout: 5 * time.Second,
},
),
fs: func() *gotenberg.FileSystem {
fs := gotenberg.NewFileSystem()
err := os.MkdirAll(fs.WorkingDirPath(), 0o755)
if err != nil {
t.Fatalf(fmt.Sprintf("expected no error but got: %v", err))
}
err = os.WriteFile(fmt.Sprintf("%s/document.txt", fs.WorkingDirPath()), []byte("Landscape"), 0o755)
if err != nil {
t.Fatalf("expected no error but got: %v", err)
}
return fs
}(),
options: Options{PdfFormats: gotenberg.PdfFormats{PdfUa: true}},
cancelledCtx: false,
start: true,
expectError: false,

View File

@@ -18,7 +18,7 @@ func init() {
// PDF with LibreOffice.
type LibreOffice struct {
api libeofficeapi.Uno
engine gotenberg.PDFEngine
engine gotenberg.PdfEngine
disableRoutes bool
}
@@ -53,12 +53,12 @@ func (mod *LibreOffice) Provision(ctx *gotenberg.Context) error {
mod.api = libreOfficeApi
provider, err = ctx.Module(new(gotenberg.PDFEngineProvider))
provider, err = ctx.Module(new(gotenberg.PdfEngineProvider))
if err != nil {
return fmt.Errorf("get PDF engine provider: %w", err)
}
engine, err := provider.(gotenberg.PDFEngineProvider).PDFEngine()
engine, err := provider.(gotenberg.PdfEngineProvider).PdfEngine()
if err != nil {
return fmt.Errorf("get PDF engine: %w", err)
}

View File

@@ -94,7 +94,7 @@ func TestLibreOffice_Provision(t *testing.T) {
mod := &struct {
gotenberg.ModuleMock
libreofficeapi.ProviderMock
gotenberg.PDFEngineProviderMock
gotenberg.PdfEngineProviderMock
}{}
mod.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return mod }}
@@ -102,7 +102,7 @@ func TestLibreOffice_Provision(t *testing.T) {
mod.LibreOfficeMock = func() (libreofficeapi.Uno, error) {
return new(libreofficeapi.ApiMock), nil
}
mod.PDFEngineMock = func() (gotenberg.PDFEngine, error) {
mod.PdfEngineMock = func() (gotenberg.PdfEngine, error) {
return nil, errors.New("foo")
}
@@ -123,7 +123,7 @@ func TestLibreOffice_Provision(t *testing.T) {
mod := &struct {
gotenberg.ModuleMock
libreofficeapi.ProviderMock
gotenberg.PDFEngineProviderMock
gotenberg.PdfEngineProviderMock
}{}
mod.DescriptorMock = func() gotenberg.ModuleDescriptor {
return gotenberg.ModuleDescriptor{ID: "bar", New: func() gotenberg.Module { return mod }}
@@ -131,8 +131,8 @@ func TestLibreOffice_Provision(t *testing.T) {
mod.LibreOfficeMock = func() (libreofficeapi.Uno, error) {
return new(libreofficeapi.ApiMock), nil
}
mod.PDFEngineMock = func() (gotenberg.PDFEngine, error) {
return new(gotenberg.PDFEngineMock), nil
mod.PdfEngineMock = func() (gotenberg.PdfEngine, error) {
return new(gotenberg.PdfEngineMock), nil
}
return gotenberg.NewContext(

View File

@@ -1,4 +1,4 @@
// Package pdfengine provides a module which interacts with LibreOffice via the
// UNO (Universal Network Objects) API and implements the [gotenberg.PDFEngine]
// UNO (Universal Network Objects) API and implements the gotenberg.PdfEngine
// interface.
package pdfengine

View File

@@ -16,7 +16,7 @@ func init() {
}
// LibreOfficePdfEngine interacts with the LibreOffice (Universal Network Objects) API
// and implements the [gotenberg.PDFEngine] interface.
// and implements the [gotenberg.PdfEngine] interface.
type LibreOfficePdfEngine struct {
unoAPI api.Uno
}
@@ -46,17 +46,18 @@ func (engine *LibreOfficePdfEngine) Provision(ctx *gotenberg.Context) error {
return nil
}
// Merge is not available for this PDF engine.
func (engine *LibreOfficePdfEngine) Merge(_ context.Context, _ *zap.Logger, _ []string, _ string) error {
return fmt.Errorf("merge PDFs with LibreOffice: %w", gotenberg.ErrPDFEngineMethodNotAvailable)
// Merge is not available in this implementation.
func (engine *LibreOfficePdfEngine) Merge(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
return fmt.Errorf("merge PDFs with LibreOffice: %w", gotenberg.ErrPdfEngineMethodNotSupported)
}
// Convert converts the given PDF to a specific PDF format. Currently, only the
// PDF/A-1a, PDF/A-2b and PDF/A-3b formats are available. If another PDF format
// is requested, it returns a [gotenberg.ErrPDFFormatNotAvailable] error.
func (engine *LibreOfficePdfEngine) Convert(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error {
// PDF/A-1a, PDF/A-2b, PDF/A-3b and PDF/UA formats are available. If another
// PDF format is requested, it returns a [gotenberg.ErrPdfFormatNotSupported]
// error.
func (engine *LibreOfficePdfEngine) Convert(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
err := engine.unoAPI.Pdf(ctx, logger, inputPath, outputPath, api.Options{
PdfFormat: format,
PdfFormats: formats,
})
if err == nil {
@@ -64,15 +65,15 @@ func (engine *LibreOfficePdfEngine) Convert(ctx context.Context, logger *zap.Log
}
if errors.Is(err, api.ErrInvalidPdfFormat) {
return fmt.Errorf("convert PDF to '%s' with LibreOffice: %w", format, gotenberg.ErrPDFFormatNotAvailable)
return fmt.Errorf("convert PDF to '%+v' with LibreOffice: %w", formats, gotenberg.ErrPdfFormatNotSupported)
}
return fmt.Errorf("convert PDF to '%s' with unoconv: %w", format, err)
return fmt.Errorf("convert PDF to '%+v' with LibreOffice: %w", formats, err)
}
// Interface guards.
var (
_ gotenberg.Module = (*LibreOfficePdfEngine)(nil)
_ gotenberg.Provisioner = (*LibreOfficePdfEngine)(nil)
_ gotenberg.PDFEngine = (*LibreOfficePdfEngine)(nil)
_ gotenberg.PdfEngine = (*LibreOfficePdfEngine)(nil)
)

View File

@@ -95,8 +95,8 @@ func TestLibreOfficePdfEngine_Provider(t *testing.T) {
},
} {
t.Run(tc.scenario, func(t *testing.T) {
mod := new(LibreOfficePdfEngine)
err := mod.Provision(tc.ctx)
engine := new(LibreOfficePdfEngine)
err := engine.Provision(tc.ctx)
if !tc.expectError && err != nil {
t.Fatalf("expected no error but got: %v", err)
@@ -110,11 +110,11 @@ func TestLibreOfficePdfEngine_Provider(t *testing.T) {
}
func TestLibreOfficePdfEngine_Merge(t *testing.T) {
mod := new(LibreOfficePdfEngine)
err := mod.Merge(context.Background(), zap.NewNop(), nil, "")
engine := new(LibreOfficePdfEngine)
err := engine.Merge(context.Background(), zap.NewNop(), nil, "")
if !errors.Is(err, gotenberg.ErrPDFEngineMethodNotAvailable) {
t.Errorf("expected error %v, but got: %v", gotenberg.ErrPDFEngineMethodNotAvailable, err)
if !errors.Is(err, gotenberg.ErrPdfEngineMethodNotSupported) {
t.Errorf("expected error %v, but got: %v", gotenberg.ErrPdfEngineMethodNotSupported, err)
}
}
@@ -154,7 +154,7 @@ func TestLibreOfficePdfEngine_Convert(t *testing.T) {
} {
t.Run(tc.scenario, func(t *testing.T) {
engine := &LibreOfficePdfEngine{unoAPI: tc.api}
err := engine.Convert(context.Background(), zap.NewNop(), "", "", "")
err := engine.Convert(context.Background(), zap.NewNop(), gotenberg.PdfFormats{}, "", "")
if !tc.expectError && err != nil {
t.Fatalf("expected no error but got: %v", err)

View File

@@ -14,7 +14,7 @@ import (
// convertRoute returns an [api.Route] which can convert LibreOffice documents
// to PDF.
func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PDFEngine) api.Route {
func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) api.Route {
return api.Route{
Method: http.MethodPost,
Path: "/forms/libreoffice/convert",
@@ -30,6 +30,9 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PDFEngine) ap
nativePdfA1aFormat bool
nativePdfFormat string
pdfFormat string
pdfa string
pdfua bool
nativePdfFormats bool
merge bool
)
@@ -40,50 +43,69 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PDFEngine) ap
Bool("nativePdfA1aFormat", &nativePdfA1aFormat, false).
String("nativePdfFormat", &nativePdfFormat, "").
String("pdfFormat", &pdfFormat, "").
String("pdfa", &pdfa, "").
Bool("pdfua", &pdfua, false).
Bool("nativePdfFormats", &nativePdfFormats, true).
Bool("merge", &merge, false).
Validate()
if err != nil {
return fmt.Errorf("validate form data: %w", err)
}
// nativePdfFormat > pdfFormat > nativePdfA1aFormat.
// FIXME: deprecated.
// pdfa > nativePdfFormat > pdfFormat > nativePdfA1aFormat.
var (
actualPdfFormat string
nativeFormat bool
actualPdfArchive string
nativeFormats bool
)
// FIXME: deprecated.
if nativePdfA1aFormat {
ctx.Log().Warn("'nativePdfA1aFormat' is deprecated; prefer 'nativePdfFormat' or 'pdfFormat' form fields instead")
actualPdfFormat = gotenberg.FormatPDFA1a
nativeFormat = true
ctx.Log().Warn("'nativePdfA1aFormat' is deprecated; prefer the 'pdfa' form field instead")
actualPdfArchive = gotenberg.PdfA1a
nativeFormats = true
}
if pdfFormat != "" {
actualPdfFormat = pdfFormat
nativeFormat = false
ctx.Log().Warn("'pdfFormat' is deprecated; prefer the 'pdfa' form field instead")
actualPdfArchive = pdfFormat
nativeFormats = false
}
if nativePdfFormat != "" {
actualPdfFormat = nativePdfFormat
nativeFormat = true
ctx.Log().Warn("'nativePdfFormat' is deprecated; prefer the 'pdfa' form field instead")
actualPdfArchive = nativePdfFormat
nativeFormats = true
}
if pdfa != "" {
actualPdfArchive = pdfa
nativeFormats = nativePdfFormats
}
if pdfua {
nativeFormats = nativePdfFormats
}
pdfFormats := gotenberg.PdfFormats{
PdfA: actualPdfArchive,
PdfUa: pdfua,
}
// Alright, let's convert each document to PDF.
outputPaths := make([]string, len(inputPaths))
for i, inputPath := range inputPaths {
outputPaths[i] = ctx.GeneratePath(".pdf")
options := libreofficeapi.Options{
Landscape: landscape,
PageRanges: nativePageRanges,
PdfFormat: nativePdfFormat,
}
if nativeFormats {
options.PdfFormats = pdfFormats
}
err = libreOffice.Pdf(ctx, ctx.Log(), inputPath, outputPaths[i], options)
if err != nil {
if errors.Is(err, libreofficeapi.ErrMalformedPageRanges) {
return api.WrapError(
@@ -108,21 +130,20 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PDFEngine) ap
}
// Now, let's check if the client want to convert this result
// PDF to a specific PDF format.
if !nativeFormat && actualPdfFormat != "" {
// PDF to specific PDF formats.
zeroValued := gotenberg.PdfFormats{}
if !nativeFormats && pdfFormats != zeroValued {
convertInputPath := outputPath
convertOutputPath := ctx.GeneratePath(".pdf")
err = engine.Convert(ctx, ctx.Log(), actualPdfFormat, convertInputPath, convertOutputPath)
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPath)
if err != nil {
if errors.Is(err, gotenberg.ErrPDFFormatNotAvailable) {
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
return api.WrapError(
fmt.Errorf("convert PDF: %w", err),
api.NewSentinelHTTPError(
http.StatusBadRequest,
fmt.Sprintf("At least one PDF engine does not handle the PDF format '%s' (pdfFormat), while other have failed to convert for other reasons", actualPdfFormat),
fmt.Sprintf("At least one PDF engine does not handle one of the PDF format in '%+v', while other have failed to convert for other reasons", pdfFormats),
),
)
}
@@ -147,23 +168,22 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PDFEngine) ap
// Ok, we don't have to merge the PDFs. Let's check if the client
// want to convert each PDF to a specific PDF format.
if !nativeFormat && actualPdfFormat != "" {
zeroValued := gotenberg.PdfFormats{}
if !nativeFormats && pdfFormats != zeroValued {
convertOutputPaths := make([]string, len(outputPaths))
for i, outputPath := range outputPaths {
convertInputPath := outputPath
convertOutputPaths[i] = ctx.GeneratePath(".pdf")
err = engine.Convert(ctx, ctx.Log(), actualPdfFormat, convertInputPath, convertOutputPaths[i])
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPaths[i])
if err != nil {
if errors.Is(err, gotenberg.ErrPDFFormatNotAvailable) {
if errors.Is(err, gotenberg.ErrPdfFormatNotSupported) {
return api.WrapError(
fmt.Errorf("convert PDF: %w", err),
api.NewSentinelHTTPError(
http.StatusBadRequest,
fmt.Sprintf("At least one PDF engine does not handle the PDF format '%s' (pdfFormat), while other have failed to convert for other reasons", actualPdfFormat),
fmt.Sprintf("At least one PDF engine does not handle one of the PDF format in '%+v', while other have failed to convert for other reasons", pdfFormats),
),
)
}

View File

@@ -19,7 +19,7 @@ func TestConvertRoute(t *testing.T) {
scenario string
ctx *api.ContextMock
libreOffice libreofficeapi.Uno
engine gotenberg.PDFEngine
engine gotenberg.PdfEngine
expectOptions libreofficeapi.Options
expectError bool
expectHttpError bool
@@ -81,7 +81,7 @@ func TestConvertRoute(t *testing.T) {
expectOutputPathsCount: 0,
},
{
scenario: "ErrPDFFormatNotAvailable (single file)",
scenario: "ErrPdfFormatNotSupported (single file)",
ctx: func() *api.ContextMock {
ctx := &api.ContextMock{Context: new(api.Context)}
ctx.SetFiles(map[string]string{
@@ -102,9 +102,9 @@ func TestConvertRoute(t *testing.T) {
return []string{".docx"}
},
},
engine: &gotenberg.PDFEngineMock{
ConvertMock: func(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error {
return gotenberg.ErrPDFFormatNotAvailable
engine: &gotenberg.PdfEngineMock{
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
return gotenberg.ErrPdfFormatNotSupported
},
},
expectError: true,
@@ -121,7 +121,7 @@ func TestConvertRoute(t *testing.T) {
})
ctx.SetValues(map[string][]string{
"pdfFormat": {
gotenberg.FormatPDFA1a,
gotenberg.PdfA1a,
},
})
return ctx
@@ -134,8 +134,8 @@ func TestConvertRoute(t *testing.T) {
return []string{".docx"}
},
},
engine: &gotenberg.PDFEngineMock{
ConvertMock: func(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error {
engine: &gotenberg.PdfEngineMock{
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
return errors.New("foo")
},
},
@@ -209,15 +209,18 @@ func TestConvertRoute(t *testing.T) {
expectOutputPathsCount: 2,
},
{
scenario: "success with PDF format (single file)",
scenario: "success with non-native PDF/A (single file)",
ctx: func() *api.ContextMock {
ctx := &api.ContextMock{Context: new(api.Context)}
ctx.SetFiles(map[string]string{
"document.docx": "/document.docx",
})
ctx.SetValues(map[string][]string{
"pdfFormat": {
gotenberg.FormatPDFA1a,
"pdfa": {
gotenberg.PdfA1a,
},
"nativePdfFormats": {
"false",
},
})
return ctx
@@ -230,8 +233,8 @@ func TestConvertRoute(t *testing.T) {
return []string{".docx"}
},
},
engine: &gotenberg.PDFEngineMock{
ConvertMock: func(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error {
engine: &gotenberg.PdfEngineMock{
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
return nil
},
},
@@ -240,7 +243,7 @@ func TestConvertRoute(t *testing.T) {
expectOutputPathsCount: 1,
},
{
scenario: "success with every PDF formats form field (single file)",
scenario: "success with every non-native PDF/A & PDF/UA form fields (single file)",
ctx: func() *api.ContextMock {
ctx := &api.ContextMock{Context: new(api.Context)}
ctx.SetFiles(map[string]string{
@@ -251,10 +254,19 @@ func TestConvertRoute(t *testing.T) {
"true",
},
"pdfFormat": {
gotenberg.FormatPDFA1a,
gotenberg.PdfA1a,
},
"nativePdfFormat": {
gotenberg.FormatPDFA1a,
gotenberg.PdfA1a,
},
"pdfa": {
gotenberg.PdfA1a,
},
"pdfua": {
"true",
},
"nativePdfFormats": {
"false",
},
})
return ctx
@@ -267,8 +279,8 @@ func TestConvertRoute(t *testing.T) {
return []string{".docx"}
},
},
engine: &gotenberg.PDFEngineMock{
ConvertMock: func(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error {
engine: &gotenberg.PdfEngineMock{
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
return nil
},
},
@@ -299,7 +311,7 @@ func TestConvertRoute(t *testing.T) {
return []string{".docx"}
},
},
engine: &gotenberg.PDFEngineMock{
engine: &gotenberg.PdfEngineMock{
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
return errors.New("foo")
},
@@ -309,7 +321,7 @@ func TestConvertRoute(t *testing.T) {
expectOutputPathsCount: 0,
},
{
scenario: "ErrPDFFormatNotAvailable (merge)",
scenario: "ErrPdfFormatNotSupported (merge)",
ctx: func() *api.ContextMock {
ctx := &api.ContextMock{Context: new(api.Context)}
ctx.SetFiles(map[string]string{
@@ -320,9 +332,12 @@ func TestConvertRoute(t *testing.T) {
"merge": {
"true",
},
"pdfFormat": {
"pdfa": {
"foo",
},
"nativePdfFormats": {
"false",
},
})
return ctx
}(),
@@ -334,12 +349,12 @@ func TestConvertRoute(t *testing.T) {
return []string{".docx"}
},
},
engine: &gotenberg.PDFEngineMock{
engine: &gotenberg.PdfEngineMock{
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
return nil
},
ConvertMock: func(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error {
return gotenberg.ErrPDFFormatNotAvailable
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
return gotenberg.ErrPdfFormatNotSupported
},
},
expectError: true,
@@ -359,8 +374,11 @@ func TestConvertRoute(t *testing.T) {
"merge": {
"true",
},
"pdfFormat": {
gotenberg.FormatPDFA1a,
"pdfa": {
gotenberg.PdfA1a,
},
"nativePdfFormats": {
"false",
},
})
return ctx
@@ -373,11 +391,11 @@ func TestConvertRoute(t *testing.T) {
return []string{".docx"}
},
},
engine: &gotenberg.PDFEngineMock{
engine: &gotenberg.PdfEngineMock{
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
return nil
},
ConvertMock: func(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error {
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
return errors.New("foo")
},
},
@@ -409,7 +427,7 @@ func TestConvertRoute(t *testing.T) {
return []string{".docx"}
},
},
engine: &gotenberg.PDFEngineMock{
engine: &gotenberg.PdfEngineMock{
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
return nil
},
@@ -441,7 +459,7 @@ func TestConvertRoute(t *testing.T) {
return []string{".docx"}
},
},
engine: &gotenberg.PDFEngineMock{
engine: &gotenberg.PdfEngineMock{
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
return nil
},
@@ -451,7 +469,7 @@ func TestConvertRoute(t *testing.T) {
expectOutputPathsCount: 1,
},
{
scenario: "success with PDF format (merge)",
scenario: "success with non-native PDF/A (merge)",
ctx: func() *api.ContextMock {
ctx := &api.ContextMock{Context: new(api.Context)}
ctx.SetFiles(map[string]string{
@@ -462,8 +480,11 @@ func TestConvertRoute(t *testing.T) {
"merge": {
"true",
},
"pdfFormat": {
gotenberg.FormatPDFA1a,
"pdfa": {
gotenberg.PdfA1a,
},
"nativePdfFormats": {
"false",
},
})
return ctx
@@ -476,11 +497,11 @@ func TestConvertRoute(t *testing.T) {
return []string{".docx"}
},
},
engine: &gotenberg.PDFEngineMock{
engine: &gotenberg.PdfEngineMock{
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
return nil
},
ConvertMock: func(ctx context.Context, logger *zap.Logger, format, inputPath, outputPath string) error {
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
return nil
},
},