mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-18 05:02:15 +01:00
chore(pdfengines): add stubs for common workflows
This commit is contained in:
@@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gotenberg/gotenberg/v8/pkg/gotenberg"
|
"github.com/gotenberg/gotenberg/v8/pkg/gotenberg"
|
||||||
"github.com/gotenberg/gotenberg/v8/pkg/modules/api"
|
"github.com/gotenberg/gotenberg/v8/pkg/modules/api"
|
||||||
|
"github.com/gotenberg/gotenberg/v8/pkg/modules/pdfengines"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FormDataChromiumOptions creates [Options] from the form data. Fallback to
|
// FormDataChromiumOptions creates [Options] from the form data. Fallback to
|
||||||
@@ -316,39 +317,6 @@ func FormDataChromiumScreenshotOptions(ctx *api.Context) (*api.FormData, Screens
|
|||||||
return form, screenshotOptions
|
return form, screenshotOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// FormDataChromiumPdfFormats creates [gotenberg.PdfFormats] from the form
|
|
||||||
// data. Fallback to default value if the considered key is not present.
|
|
||||||
func FormDataChromiumPdfFormats(form *api.FormData) gotenberg.PdfFormats {
|
|
||||||
var (
|
|
||||||
pdfa string
|
|
||||||
pdfua bool
|
|
||||||
)
|
|
||||||
|
|
||||||
form.
|
|
||||||
String("pdfa", &pdfa, "").
|
|
||||||
Bool("pdfua", &pdfua, false)
|
|
||||||
|
|
||||||
return gotenberg.PdfFormats{
|
|
||||||
PdfA: pdfa,
|
|
||||||
PdfUa: pdfua,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormDataPdfMetadata creates metadata object from the form data.
|
|
||||||
func FormDataPdfMetadata(form *api.FormData) map[string]interface{} {
|
|
||||||
var metadata map[string]interface{}
|
|
||||||
form.Custom("metadata", func(value string) error {
|
|
||||||
if len(value) > 0 {
|
|
||||||
err := json.Unmarshal([]byte(value), &metadata)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unmarshal metadata: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return metadata
|
|
||||||
}
|
|
||||||
|
|
||||||
// convertUrlRoute returns an [api.Route] which can convert a URL to PDF.
|
// convertUrlRoute returns an [api.Route] which can convert a URL to PDF.
|
||||||
func convertUrlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
func convertUrlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
||||||
return api.Route{
|
return api.Route{
|
||||||
@@ -358,8 +326,8 @@ func convertUrlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
|||||||
Handler: func(c echo.Context) error {
|
Handler: func(c echo.Context) error {
|
||||||
ctx := c.Get("context").(*api.Context)
|
ctx := c.Get("context").(*api.Context)
|
||||||
form, options := FormDataChromiumPdfOptions(ctx)
|
form, options := FormDataChromiumPdfOptions(ctx)
|
||||||
pdfFormats := FormDataChromiumPdfFormats(form)
|
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
||||||
metadata := FormDataPdfMetadata(form)
|
metadata := pdfengines.FormDataPdfMetadata(form)
|
||||||
|
|
||||||
var url string
|
var url string
|
||||||
err := form.
|
err := form.
|
||||||
@@ -418,8 +386,8 @@ func convertHtmlRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
|||||||
Handler: func(c echo.Context) error {
|
Handler: func(c echo.Context) error {
|
||||||
ctx := c.Get("context").(*api.Context)
|
ctx := c.Get("context").(*api.Context)
|
||||||
form, options := FormDataChromiumPdfOptions(ctx)
|
form, options := FormDataChromiumPdfOptions(ctx)
|
||||||
pdfFormats := FormDataChromiumPdfFormats(form)
|
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
||||||
metadata := FormDataPdfMetadata(form)
|
metadata := pdfengines.FormDataPdfMetadata(form)
|
||||||
|
|
||||||
var inputPath string
|
var inputPath string
|
||||||
err := form.
|
err := form.
|
||||||
@@ -480,8 +448,8 @@ func convertMarkdownRoute(chromium Api, engine gotenberg.PdfEngine) api.Route {
|
|||||||
Handler: func(c echo.Context) error {
|
Handler: func(c echo.Context) error {
|
||||||
ctx := c.Get("context").(*api.Context)
|
ctx := c.Get("context").(*api.Context)
|
||||||
form, options := FormDataChromiumPdfOptions(ctx)
|
form, options := FormDataChromiumPdfOptions(ctx)
|
||||||
pdfFormats := FormDataChromiumPdfFormats(form)
|
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
||||||
metadata := FormDataPdfMetadata(form)
|
metadata := pdfengines.FormDataPdfMetadata(form)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
inputPath string
|
inputPath string
|
||||||
@@ -664,34 +632,19 @@ func convertUrl(ctx *api.Context, chromium Api, engine gotenberg.PdfEngine, url
|
|||||||
return fmt.Errorf("convert to PDF: %w", err)
|
return fmt.Errorf("convert to PDF: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// So far so good, the URL has been converted to PDF.
|
outputPaths, err := pdfengines.ConvertStub(ctx, engine, pdfFormats, []string{outputPath})
|
||||||
// Now, let's check if the client want to convert the resulting PDF
|
|
||||||
// to specific formats.
|
|
||||||
zeroValued := gotenberg.PdfFormats{}
|
|
||||||
if pdfFormats != zeroValued {
|
|
||||||
convertInputPath := outputPath
|
|
||||||
convertOutputPath := ctx.GeneratePath(".pdf")
|
|
||||||
|
|
||||||
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("convert PDF: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Important: the output path is now the converted file.
|
|
||||||
outputPath = convertOutputPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes and potentially overrides metadata entries, if any.
|
|
||||||
if len(metadata) > 0 {
|
|
||||||
err = engine.WriteMetadata(ctx, ctx.Log(), metadata, outputPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("write metadata: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = ctx.AddOutputPaths(outputPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("add output path: %w", err)
|
return fmt.Errorf("convert PDF: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = pdfengines.WriteMetadataStub(ctx, engine, metadata, outputPaths)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("write metadata: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ctx.AddOutputPaths(outputPaths...)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("add output paths: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -603,125 +603,6 @@ func TestFormDataChromiumScreenshotOptions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFormDataChromiumPdfFormats(t *testing.T) {
|
|
||||||
for _, tc := range []struct {
|
|
||||||
scenario string
|
|
||||||
ctx *api.ContextMock
|
|
||||||
expectedPdfFormats gotenberg.PdfFormats
|
|
||||||
expectValidationError bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
scenario: "no custom form fields",
|
|
||||||
ctx: &api.ContextMock{Context: new(api.Context)},
|
|
||||||
expectedPdfFormats: gotenberg.PdfFormats{},
|
|
||||||
expectValidationError: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scenario: "pdfa and pdfua form fields",
|
|
||||||
ctx: func() *api.ContextMock {
|
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
|
||||||
ctx.SetValues(map[string][]string{
|
|
||||||
"pdfa": {
|
|
||||||
"foo",
|
|
||||||
},
|
|
||||||
"pdfua": {
|
|
||||||
"true",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return ctx
|
|
||||||
}(),
|
|
||||||
expectedPdfFormats: gotenberg.PdfFormats{PdfA: "foo", PdfUa: true},
|
|
||||||
expectValidationError: false,
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(tc.scenario, func(t *testing.T) {
|
|
||||||
tc.ctx.SetLogger(zap.NewNop())
|
|
||||||
form := tc.ctx.Context.FormData()
|
|
||||||
actual := FormDataChromiumPdfFormats(form)
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(actual, tc.expectedPdfFormats) {
|
|
||||||
t.Fatalf("expected %+v but got: %+v", tc.expectedPdfFormats, actual)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := form.Validate()
|
|
||||||
|
|
||||||
if tc.expectValidationError && err == nil {
|
|
||||||
t.Fatal("expected validation error but got none", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !tc.expectValidationError && err != nil {
|
|
||||||
t.Fatalf("expected no validation error but got: %v", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFormDataPdfMetadata(t *testing.T) {
|
|
||||||
for _, tc := range []struct {
|
|
||||||
scenario string
|
|
||||||
ctx *api.ContextMock
|
|
||||||
expectedMetadata map[string]interface{}
|
|
||||||
expectValidationError bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
scenario: "no metadata form field",
|
|
||||||
ctx: &api.ContextMock{Context: new(api.Context)},
|
|
||||||
expectedMetadata: nil,
|
|
||||||
expectValidationError: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scenario: "invalid metadata form field",
|
|
||||||
ctx: func() *api.ContextMock {
|
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
|
||||||
ctx.SetValues(map[string][]string{
|
|
||||||
"metadata": {
|
|
||||||
"foo",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return ctx
|
|
||||||
}(),
|
|
||||||
expectedMetadata: nil,
|
|
||||||
expectValidationError: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scenario: "valid metadata form field",
|
|
||||||
ctx: func() *api.ContextMock {
|
|
||||||
ctx := &api.ContextMock{Context: new(api.Context)}
|
|
||||||
ctx.SetValues(map[string][]string{
|
|
||||||
"metadata": {
|
|
||||||
"{\"foo\":\"bar\"}",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return ctx
|
|
||||||
}(),
|
|
||||||
expectedMetadata: map[string]interface{}{
|
|
||||||
"foo": "bar",
|
|
||||||
},
|
|
||||||
expectValidationError: false,
|
|
||||||
},
|
|
||||||
} {
|
|
||||||
t.Run(tc.scenario, func(t *testing.T) {
|
|
||||||
tc.ctx.SetLogger(zap.NewNop())
|
|
||||||
form := tc.ctx.Context.FormData()
|
|
||||||
actual := FormDataPdfMetadata(form)
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(actual, tc.expectedMetadata) {
|
|
||||||
t.Fatalf("expected %+v but got: %+v", tc.expectedMetadata, actual)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := form.Validate()
|
|
||||||
|
|
||||||
if tc.expectValidationError && err == nil {
|
|
||||||
t.Fatal("expected validation error but got none", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !tc.expectValidationError && err != nil {
|
|
||||||
t.Fatalf("expected no validation error but got: %v", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConvertUrlRoute(t *testing.T) {
|
func TestConvertUrlRoute(t *testing.T) {
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
scenario string
|
scenario string
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/gotenberg/gotenberg/v8/pkg/gotenberg"
|
"github.com/gotenberg/gotenberg/v8/pkg/gotenberg"
|
||||||
"github.com/gotenberg/gotenberg/v8/pkg/modules/api"
|
"github.com/gotenberg/gotenberg/v8/pkg/modules/api"
|
||||||
libreofficeapi "github.com/gotenberg/gotenberg/v8/pkg/modules/libreoffice/api"
|
libreofficeapi "github.com/gotenberg/gotenberg/v8/pkg/modules/libreoffice/api"
|
||||||
|
"github.com/gotenberg/gotenberg/v8/pkg/modules/pdfengines"
|
||||||
)
|
)
|
||||||
|
|
||||||
// convertRoute returns an [api.Route] which can convert LibreOffice documents
|
// convertRoute returns an [api.Route] which can convert LibreOffice documents
|
||||||
@@ -26,7 +27,10 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
ctx := c.Get("context").(*api.Context)
|
ctx := c.Get("context").(*api.Context)
|
||||||
defaultOptions := libreofficeapi.DefaultOptions()
|
defaultOptions := libreofficeapi.DefaultOptions()
|
||||||
|
|
||||||
// Let's get the data from the form and validate them.
|
form := ctx.FormData()
|
||||||
|
pdfFormats := pdfengines.FormDataPdfFormats(form)
|
||||||
|
metadata := pdfengines.FormDataPdfMetadata(form)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
inputPaths []string
|
inputPaths []string
|
||||||
password string
|
password string
|
||||||
@@ -51,14 +55,11 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
quality int
|
quality int
|
||||||
reduceImageResolution bool
|
reduceImageResolution bool
|
||||||
maxImageResolution int
|
maxImageResolution int
|
||||||
pdfa string
|
|
||||||
pdfua bool
|
|
||||||
nativePdfFormats bool
|
nativePdfFormats bool
|
||||||
merge bool
|
merge bool
|
||||||
metadata map[string]interface{}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
err := ctx.FormData().
|
err := form.
|
||||||
MandatoryPaths(libreOffice.Extensions(), &inputPaths).
|
MandatoryPaths(libreOffice.Extensions(), &inputPaths).
|
||||||
String("password", &password, defaultOptions.Password).
|
String("password", &password, defaultOptions.Password).
|
||||||
Bool("landscape", &landscape, defaultOptions.Landscape).
|
Bool("landscape", &landscape, defaultOptions.Landscape).
|
||||||
@@ -120,8 +121,6 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
maxImageResolution = intValue
|
maxImageResolution = intValue
|
||||||
return nil
|
return nil
|
||||||
}).
|
}).
|
||||||
String("pdfa", &pdfa, "").
|
|
||||||
Bool("pdfua", &pdfua, false).
|
|
||||||
Bool("nativePdfFormats", &nativePdfFormats, true).
|
Bool("nativePdfFormats", &nativePdfFormats, true).
|
||||||
Bool("merge", &merge, false).
|
Bool("merge", &merge, false).
|
||||||
Custom("metadata", func(value string) error {
|
Custom("metadata", func(value string) error {
|
||||||
@@ -138,12 +137,6 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
return fmt.Errorf("validate form data: %w", err)
|
return fmt.Errorf("validate form data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pdfFormats := gotenberg.PdfFormats{
|
|
||||||
PdfA: pdfa,
|
|
||||||
PdfUa: pdfua,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alright, let's convert each document to PDF.
|
|
||||||
outputPaths := make([]string, len(inputPaths))
|
outputPaths := make([]string, len(inputPaths))
|
||||||
for i, inputPath := range inputPaths {
|
for i, inputPath := range inputPaths {
|
||||||
outputPaths[i] = ctx.GeneratePath(".pdf")
|
outputPaths[i] = ctx.GeneratePath(".pdf")
|
||||||
@@ -206,11 +199,8 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// So far so good, let's check if we have to merge the PDFs.
|
if merge {
|
||||||
if len(outputPaths) > 1 && merge {
|
outputPath, err := pdfengines.MergeStub(ctx, engine, outputPaths)
|
||||||
outputPath := ctx.GeneratePath(".pdf")
|
|
||||||
|
|
||||||
err = engine.Merge(ctx, ctx.Log(), outputPaths, outputPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("merge PDFs: %w", err)
|
return fmt.Errorf("merge PDFs: %w", err)
|
||||||
}
|
}
|
||||||
@@ -219,34 +209,16 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
outputPaths = []string{outputPath}
|
outputPaths = []string{outputPath}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's check if the client want to convert each PDF to a specific
|
if !nativePdfFormats {
|
||||||
// PDF format.
|
outputPaths, err = pdfengines.ConvertStub(ctx, engine, pdfFormats, outputPaths)
|
||||||
zeroValued := gotenberg.PdfFormats{}
|
if err != nil {
|
||||||
if !nativePdfFormats && pdfFormats != zeroValued {
|
return fmt.Errorf("convert PDFs: %w", err)
|
||||||
convertOutputPaths := make([]string, len(outputPaths))
|
|
||||||
|
|
||||||
for i, outputPath := range outputPaths {
|
|
||||||
convertInputPath := outputPath
|
|
||||||
convertOutputPaths[i] = ctx.GeneratePath(".pdf")
|
|
||||||
|
|
||||||
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPaths[i])
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("convert PDF: %w", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Important: the output paths are now the converted files.
|
|
||||||
outputPaths = convertOutputPaths
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes and potentially overrides metadata entries, if any.
|
err = pdfengines.WriteMetadataStub(ctx, engine, metadata, outputPaths)
|
||||||
if len(metadata) > 0 {
|
if err != nil {
|
||||||
for _, outputPath := range outputPaths {
|
return fmt.Errorf("write metadata: %w", err)
|
||||||
err = engine.WriteMetadata(ctx, ctx.Log(), metadata, outputPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("write metadata: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(outputPaths) > 1 {
|
if len(outputPaths) > 1 {
|
||||||
@@ -263,8 +235,6 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last but not least, add the output paths to the context so that
|
|
||||||
// the API is able to send them as a response to the client.
|
|
||||||
err = ctx.AddOutputPaths(outputPaths...)
|
err = ctx.AddOutputPaths(outputPaths...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("add output paths: %w", err)
|
return fmt.Errorf("add output paths: %w", err)
|
||||||
|
|||||||
@@ -13,6 +13,98 @@ import (
|
|||||||
"github.com/gotenberg/gotenberg/v8/pkg/modules/api"
|
"github.com/gotenberg/gotenberg/v8/pkg/modules/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FormDataPdfFormats creates [gotenberg.PdfFormats] from the form data.
|
||||||
|
// Fallback to default value if the considered key is not present.
|
||||||
|
func FormDataPdfFormats(form *api.FormData) gotenberg.PdfFormats {
|
||||||
|
var (
|
||||||
|
pdfa string
|
||||||
|
pdfua bool
|
||||||
|
)
|
||||||
|
|
||||||
|
form.
|
||||||
|
String("pdfa", &pdfa, "").
|
||||||
|
Bool("pdfua", &pdfua, false)
|
||||||
|
|
||||||
|
return gotenberg.PdfFormats{
|
||||||
|
PdfA: pdfa,
|
||||||
|
PdfUa: pdfua,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FormDataPdfMetadata creates metadata object from the form data.
|
||||||
|
func FormDataPdfMetadata(form *api.FormData) map[string]interface{} {
|
||||||
|
var metadata map[string]interface{}
|
||||||
|
form.Custom("metadata", func(value string) error {
|
||||||
|
if len(value) > 0 {
|
||||||
|
err := json.Unmarshal([]byte(value), &metadata)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal metadata: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
// MergeStub merges given PDFs. If only one input PDF, it does nothing and
|
||||||
|
// returns the corresponding input path.
|
||||||
|
func MergeStub(ctx *api.Context, engine gotenberg.PdfEngine, inputPaths []string) (string, error) {
|
||||||
|
if len(inputPaths) == 0 {
|
||||||
|
return "", errors.New("no input paths")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(inputPaths) == 1 {
|
||||||
|
return inputPaths[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPath := ctx.GeneratePath(".pdf")
|
||||||
|
err := engine.Merge(ctx, ctx.Log(), inputPaths, outputPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("merge %d PDFs: %w", len(inputPaths), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConvertStub transforms a given PDF to the specified formats defined in
|
||||||
|
// [gotenberg.PdfFormats]. If no format, it does nothing and returns the input
|
||||||
|
// paths.
|
||||||
|
func ConvertStub(ctx *api.Context, engine gotenberg.PdfEngine, formats gotenberg.PdfFormats, inputPaths []string) ([]string, error) {
|
||||||
|
zeroValued := gotenberg.PdfFormats{}
|
||||||
|
if formats == zeroValued {
|
||||||
|
return inputPaths, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
outputPaths := make([]string, len(inputPaths))
|
||||||
|
for i, inputPath := range inputPaths {
|
||||||
|
outputPaths[i] = ctx.GeneratePath(".pdf")
|
||||||
|
|
||||||
|
err := engine.Convert(ctx, ctx.Log(), formats, inputPath, outputPaths[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("convert '%s': %w", inputPath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return outputPaths, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteMetadataStub writes the metadata into PDF files. If no metadata, it
|
||||||
|
// does nothing.
|
||||||
|
func WriteMetadataStub(ctx *api.Context, engine gotenberg.PdfEngine, metadata map[string]interface{}, inputPaths []string) error {
|
||||||
|
if len(metadata) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, inputPath := range inputPaths {
|
||||||
|
err := engine.WriteMetadata(ctx, ctx.Log(), metadata, inputPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("write metadata into '%s': %w", inputPath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// mergeRoute returns an [api.Route] which can merge PDFs.
|
// mergeRoute returns an [api.Route] which can merge PDFs.
|
||||||
func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
||||||
return api.Route{
|
return api.Route{
|
||||||
@@ -22,75 +114,37 @@ func mergeRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
Handler: func(c echo.Context) error {
|
Handler: func(c echo.Context) error {
|
||||||
ctx := c.Get("context").(*api.Context)
|
ctx := c.Get("context").(*api.Context)
|
||||||
|
|
||||||
// Let's get the data from the form and validate them.
|
form := ctx.FormData()
|
||||||
var (
|
pdfFormats := FormDataPdfFormats(form)
|
||||||
inputPaths []string
|
metadata := FormDataPdfMetadata(form)
|
||||||
pdfa string
|
|
||||||
pdfua bool
|
|
||||||
metadata map[string]interface{}
|
|
||||||
)
|
|
||||||
|
|
||||||
err := ctx.FormData().
|
var inputPaths []string
|
||||||
|
err := form.
|
||||||
MandatoryPaths([]string{".pdf"}, &inputPaths).
|
MandatoryPaths([]string{".pdf"}, &inputPaths).
|
||||||
String("pdfa", &pdfa, "").
|
|
||||||
Bool("pdfua", &pdfua, false).
|
|
||||||
Custom("metadata", func(value string) error {
|
|
||||||
if len(value) > 0 {
|
|
||||||
err := json.Unmarshal([]byte(value), &metadata)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unmarshal metadata: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}).
|
|
||||||
Validate()
|
Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("validate form data: %w", err)
|
return fmt.Errorf("validate form data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pdfFormats := gotenberg.PdfFormats{
|
|
||||||
PdfA: pdfa,
|
|
||||||
PdfUa: pdfua,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alright, let's merge the PDFs.
|
|
||||||
outputPath := ctx.GeneratePath(".pdf")
|
outputPath := ctx.GeneratePath(".pdf")
|
||||||
|
|
||||||
err = engine.Merge(ctx, ctx.Log(), inputPaths, outputPath)
|
err = engine.Merge(ctx, ctx.Log(), inputPaths, outputPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("merge PDFs: %w", err)
|
return fmt.Errorf("merge PDFs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// So far so good, the PDFs are merged into one unique PDF.
|
outputPaths, err := ConvertStub(ctx, engine, pdfFormats, []string{outputPath})
|
||||||
// Now, let's check if the client want to convert this result PDF
|
|
||||||
// to specific PDF formats.
|
|
||||||
zeroValued := gotenberg.PdfFormats{}
|
|
||||||
if pdfFormats != zeroValued {
|
|
||||||
convertInputPath := outputPath
|
|
||||||
convertOutputPath := ctx.GeneratePath(".pdf")
|
|
||||||
|
|
||||||
err = engine.Convert(ctx, ctx.Log(), pdfFormats, convertInputPath, convertOutputPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("convert PDF: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Important: the output path is now the converted file.
|
|
||||||
outputPath = convertOutputPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes and potentially overrides metadata entries, if any.
|
|
||||||
if len(metadata) > 0 {
|
|
||||||
err = engine.WriteMetadata(ctx, ctx.Log(), metadata, outputPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("write metadata: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last but not least, add the output path to the context so that
|
|
||||||
// the API is able to send it as a response to the client.
|
|
||||||
err = ctx.AddOutputPaths(outputPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("add output path: %w", err)
|
return fmt.Errorf("convert PDF: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = WriteMetadataStub(ctx, engine, metadata, outputPaths)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("write metadata: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ctx.AddOutputPaths(outputPaths...)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("add output paths: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -108,27 +162,17 @@ func convertRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
Handler: func(c echo.Context) error {
|
Handler: func(c echo.Context) error {
|
||||||
ctx := c.Get("context").(*api.Context)
|
ctx := c.Get("context").(*api.Context)
|
||||||
|
|
||||||
// Let's get the data from the form and validate them.
|
form := ctx.FormData()
|
||||||
var (
|
pdfFormats := FormDataPdfFormats(form)
|
||||||
inputPaths []string
|
|
||||||
pdfa string
|
|
||||||
pdfua bool
|
|
||||||
)
|
|
||||||
|
|
||||||
err := ctx.FormData().
|
var inputPaths []string
|
||||||
|
err := form.
|
||||||
MandatoryPaths([]string{".pdf"}, &inputPaths).
|
MandatoryPaths([]string{".pdf"}, &inputPaths).
|
||||||
String("pdfa", &pdfa, "").
|
|
||||||
Bool("pdfua", &pdfua, false).
|
|
||||||
Validate()
|
Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("validate form data: %w", err)
|
return fmt.Errorf("validate form data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pdfFormats := gotenberg.PdfFormats{
|
|
||||||
PdfA: pdfa,
|
|
||||||
PdfUa: pdfua,
|
|
||||||
}
|
|
||||||
|
|
||||||
zeroValued := gotenberg.PdfFormats{}
|
zeroValued := gotenberg.PdfFormats{}
|
||||||
if pdfFormats == zeroValued {
|
if pdfFormats == zeroValued {
|
||||||
return api.WrapError(
|
return api.WrapError(
|
||||||
@@ -140,18 +184,14 @@ func convertRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alright, let's convert the PDFs.
|
outputPaths, err := ConvertStub(ctx, engine, pdfFormats, inputPaths)
|
||||||
outputPaths := make([]string, len(inputPaths))
|
if err != nil {
|
||||||
for i, inputPath := range inputPaths {
|
return fmt.Errorf("convert PDFs: %w", err)
|
||||||
outputPaths[i] = ctx.GeneratePath(".pdf")
|
}
|
||||||
|
|
||||||
err = engine.Convert(ctx, ctx.Log(), pdfFormats, inputPath, outputPaths[i])
|
if len(outputPaths) > 1 {
|
||||||
if err != nil {
|
// If .zip archive, keep the original filename.
|
||||||
return fmt.Errorf("convert PDF: %w", err)
|
for i, inputPath := range inputPaths {
|
||||||
}
|
|
||||||
|
|
||||||
if len(outputPaths) > 1 {
|
|
||||||
// If .zip archive, keep the original filename.
|
|
||||||
err = ctx.Rename(outputPaths[i], inputPath)
|
err = ctx.Rename(outputPaths[i], inputPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("rename output path: %w", err)
|
return fmt.Errorf("rename output path: %w", err)
|
||||||
@@ -161,8 +201,6 @@ func convertRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last but not least, add the output paths to the context so that
|
|
||||||
// the API is able to send them as a response to the client.
|
|
||||||
err = ctx.AddOutputPaths(outputPaths...)
|
err = ctx.AddOutputPaths(outputPaths...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("add output paths: %w", err)
|
return fmt.Errorf("add output paths: %w", err)
|
||||||
@@ -182,9 +220,7 @@ func readMetadataRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
Handler: func(c echo.Context) error {
|
Handler: func(c echo.Context) error {
|
||||||
ctx := c.Get("context").(*api.Context)
|
ctx := c.Get("context").(*api.Context)
|
||||||
|
|
||||||
// Let's get the data from the form and validate them.
|
|
||||||
var inputPaths []string
|
var inputPaths []string
|
||||||
|
|
||||||
err := ctx.FormData().
|
err := ctx.FormData().
|
||||||
MandatoryPaths([]string{".pdf"}, &inputPaths).
|
MandatoryPaths([]string{".pdf"}, &inputPaths).
|
||||||
Validate()
|
Validate()
|
||||||
@@ -192,7 +228,6 @@ func readMetadataRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
return fmt.Errorf("validate form data: %w", err)
|
return fmt.Errorf("validate form data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alright, let's read the metadata.
|
|
||||||
res := make(map[string]map[string]interface{}, len(inputPaths))
|
res := make(map[string]map[string]interface{}, len(inputPaths))
|
||||||
for _, inputPath := range inputPaths {
|
for _, inputPath := range inputPaths {
|
||||||
metadata, err := engine.ReadMetadata(ctx, ctx.Log(), inputPath)
|
metadata, err := engine.ReadMetadata(ctx, ctx.Log(), inputPath)
|
||||||
@@ -223,7 +258,6 @@ func writeMetadataRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
Handler: func(c echo.Context) error {
|
Handler: func(c echo.Context) error {
|
||||||
ctx := c.Get("context").(*api.Context)
|
ctx := c.Get("context").(*api.Context)
|
||||||
|
|
||||||
// Let's get the data from the form and validate them.
|
|
||||||
var (
|
var (
|
||||||
inputPaths []string
|
inputPaths []string
|
||||||
metadata map[string]interface{}
|
metadata map[string]interface{}
|
||||||
@@ -248,16 +282,11 @@ func writeMetadataRoute(engine gotenberg.PdfEngine) api.Route {
|
|||||||
return fmt.Errorf("validate form data: %w", err)
|
return fmt.Errorf("validate form data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alright, let's convert the PDFs.
|
err = WriteMetadataStub(ctx, engine, metadata, inputPaths)
|
||||||
for _, inputPath := range inputPaths {
|
if err != nil {
|
||||||
err = engine.WriteMetadata(ctx, ctx.Log(), metadata, inputPath)
|
return fmt.Errorf("write metadata: %w", err)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("write metadata: %w", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last but not least, add the output paths to the context so that
|
|
||||||
// the API is able to send them as a response to the client.
|
|
||||||
err = ctx.AddOutputPaths(inputPaths...)
|
err = ctx.AddOutputPaths(inputPaths...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("add output paths: %w", err)
|
return fmt.Errorf("add output paths: %w", err)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -16,6 +17,287 @@ import (
|
|||||||
"github.com/gotenberg/gotenberg/v8/pkg/modules/api"
|
"github.com/gotenberg/gotenberg/v8/pkg/modules/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestFormDataPdfFormats(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
scenario string
|
||||||
|
ctx *api.ContextMock
|
||||||
|
expectedPdfFormats gotenberg.PdfFormats
|
||||||
|
expectValidationError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
scenario: "no custom form fields",
|
||||||
|
ctx: &api.ContextMock{Context: new(api.Context)},
|
||||||
|
expectedPdfFormats: gotenberg.PdfFormats{},
|
||||||
|
expectValidationError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "pdfa and pdfua form fields",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"pdfa": {
|
||||||
|
"foo",
|
||||||
|
},
|
||||||
|
"pdfua": {
|
||||||
|
"true",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
expectedPdfFormats: gotenberg.PdfFormats{PdfA: "foo", PdfUa: true},
|
||||||
|
expectValidationError: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.scenario, func(t *testing.T) {
|
||||||
|
tc.ctx.SetLogger(zap.NewNop())
|
||||||
|
form := tc.ctx.Context.FormData()
|
||||||
|
actual := FormDataPdfFormats(form)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, tc.expectedPdfFormats) {
|
||||||
|
t.Fatalf("expected %+v but got: %+v", tc.expectedPdfFormats, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := form.Validate()
|
||||||
|
|
||||||
|
if tc.expectValidationError && err == nil {
|
||||||
|
t.Fatal("expected validation error but got none", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tc.expectValidationError && err != nil {
|
||||||
|
t.Fatalf("expected no validation error but got: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFormDataPdfMetadata(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
scenario string
|
||||||
|
ctx *api.ContextMock
|
||||||
|
expectedMetadata map[string]interface{}
|
||||||
|
expectValidationError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
scenario: "no metadata form field",
|
||||||
|
ctx: &api.ContextMock{Context: new(api.Context)},
|
||||||
|
expectedMetadata: nil,
|
||||||
|
expectValidationError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "invalid metadata form field",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"metadata": {
|
||||||
|
"foo",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
expectedMetadata: nil,
|
||||||
|
expectValidationError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "valid metadata form field",
|
||||||
|
ctx: func() *api.ContextMock {
|
||||||
|
ctx := &api.ContextMock{Context: new(api.Context)}
|
||||||
|
ctx.SetValues(map[string][]string{
|
||||||
|
"metadata": {
|
||||||
|
"{\"foo\":\"bar\"}",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
}(),
|
||||||
|
expectedMetadata: map[string]interface{}{
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
expectValidationError: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.scenario, func(t *testing.T) {
|
||||||
|
tc.ctx.SetLogger(zap.NewNop())
|
||||||
|
form := tc.ctx.Context.FormData()
|
||||||
|
actual := FormDataPdfMetadata(form)
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(actual, tc.expectedMetadata) {
|
||||||
|
t.Fatalf("expected %+v but got: %+v", tc.expectedMetadata, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := form.Validate()
|
||||||
|
|
||||||
|
if tc.expectValidationError && err == nil {
|
||||||
|
t.Fatal("expected validation error but got none", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tc.expectValidationError && err != nil {
|
||||||
|
t.Fatalf("expected no validation error but got: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeStub(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
scenario string
|
||||||
|
engine gotenberg.PdfEngine
|
||||||
|
inputPaths []string
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
scenario: "no input path (nil)",
|
||||||
|
inputPaths: nil,
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "no input path (empty)",
|
||||||
|
inputPaths: make([]string, 0),
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "only one input path",
|
||||||
|
inputPaths: []string{"my.pdf"},
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "merge error",
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
|
return errors.New("foo")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inputPaths: []string{"my.pdf", "my2.pdf"},
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "merge success",
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
MergeMock: func(ctx context.Context, logger *zap.Logger, inputPaths []string, outputPath string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inputPaths: []string{"my.pdf", "my2.pdf"},
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.scenario, func(t *testing.T) {
|
||||||
|
_, err := MergeStub(new(api.Context), tc.engine, tc.inputPaths)
|
||||||
|
|
||||||
|
if tc.expectError && err == nil {
|
||||||
|
t.Fatal("expected error but got none", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tc.expectError && err != nil {
|
||||||
|
t.Fatalf("expected no error but got: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertStub(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
scenario string
|
||||||
|
engine gotenberg.PdfEngine
|
||||||
|
pdfFormats gotenberg.PdfFormats
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
scenario: "no PDF formats",
|
||||||
|
pdfFormats: gotenberg.PdfFormats{},
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "convert error",
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
|
return errors.New("foo")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pdfFormats: gotenberg.PdfFormats{
|
||||||
|
PdfA: gotenberg.PdfA3b,
|
||||||
|
PdfUa: true,
|
||||||
|
},
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "convert success",
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
ConvertMock: func(ctx context.Context, logger *zap.Logger, formats gotenberg.PdfFormats, inputPath, outputPath string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pdfFormats: gotenberg.PdfFormats{
|
||||||
|
PdfA: gotenberg.PdfA3b,
|
||||||
|
PdfUa: true,
|
||||||
|
},
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.scenario, func(t *testing.T) {
|
||||||
|
_, err := ConvertStub(new(api.Context), tc.engine, tc.pdfFormats, []string{"my.pdf", "my2.pdf"})
|
||||||
|
|
||||||
|
if tc.expectError && err == nil {
|
||||||
|
t.Fatal("expected error but got none", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tc.expectError && err != nil {
|
||||||
|
t.Fatalf("expected no error but got: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteMetadataStub(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
scenario string
|
||||||
|
engine gotenberg.PdfEngine
|
||||||
|
metadata map[string]interface{}
|
||||||
|
expectError bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
scenario: "no metadata (nil)",
|
||||||
|
metadata: nil,
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "no metadata (empty)",
|
||||||
|
metadata: make(map[string]interface{}, 0),
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "write metadata error",
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||||
|
return errors.New("foo")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: map[string]interface{}{"foo": "bar"},
|
||||||
|
expectError: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: "write metadata success",
|
||||||
|
engine: &gotenberg.PdfEngineMock{
|
||||||
|
WriteMetadataMock: func(ctx context.Context, logger *zap.Logger, metadata map[string]interface{}, inputPath string) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
metadata: map[string]interface{}{"foo": "bar"},
|
||||||
|
expectError: false,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.scenario, func(t *testing.T) {
|
||||||
|
err := WriteMetadataStub(new(api.Context), tc.engine, tc.metadata, []string{"my.pdf", "my2.pdf"})
|
||||||
|
|
||||||
|
if tc.expectError && err == nil {
|
||||||
|
t.Fatal("expected error but got none", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !tc.expectError && err != nil {
|
||||||
|
t.Fatalf("expected no error but got: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMergeHandler(t *testing.T) {
|
func TestMergeHandler(t *testing.T) {
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
scenario string
|
scenario string
|
||||||
|
|||||||
Reference in New Issue
Block a user