diff --git a/pkg/modules/libreoffice/api/api.go b/pkg/modules/libreoffice/api/api.go index 1becfba0..f3c05e2d 100644 --- a/pkg/modules/libreoffice/api/api.go +++ b/pkg/modules/libreoffice/api/api.go @@ -41,44 +41,129 @@ type Api struct { } // Options gathers available options when converting a document to PDF. +// See: https://help.libreoffice.org/latest/en-US/text/shared/guide/pdf_params.html. type Options struct { // Landscape allows to change the orientation of the resulting PDF. - // Optional. Landscape bool // PageRanges allows to select the pages to convert. - // Optional. PageRanges string - // ExportFormFields allows to... export form fields in the resulting PDF. - // Optional. + // ExportFormFields specifies whether form fields are exported as widgets + // or only their fixed print representation is exported. ExportFormFields bool - // SinglePageSheets allows to output each sheet as a single page in the - // resulting PDF. - // Optional - SinglePageSheets bool + // AllowDuplicateFieldNames specifies whether multiple form fields exported + // are allowed to have the same field name. + AllowDuplicateFieldNames bool - // ExportNotesInMargin allows to export comments in margin. - // Optional + // ExportBookmarks specifies if bookmarks are exported to PDF. + ExportBookmarks bool + + // ExportBookmarksToPdfDestination specifies that the bookmarks contained + // in the source LibreOffice file should be exported to the PDF file as + // Named Destination. + ExportBookmarksToPdfDestination bool + + // ExportPlaceholders exports the placeholders fields visual markings only. + // The exported placeholder is ineffective. + ExportPlaceholders bool + + // ExportNotes specifies if notes are exported to PDF. + ExportNotes bool + + // ExportNotesPages specifies if notes pages are exported to PDF. + // Notes pages are available in Impress documents only. + ExportNotesPages bool + + // ExportOnlyNotesPages specifies, if the property ExportNotesPages is set + // to true, if only notes pages are exported to PDF. + ExportOnlyNotesPages bool + + // ExportNotesInMargin specifies if notes in margin are exported to PDF. ExportNotesInMargin bool - // LosslessImageCompression allows turning lossless compression on or off - // to tweak image conversion performance. - // Optional + // ConvertOooTargetToPdfTarget specifies that the target documents with + // .od[tpgs] extension, will have that extension changed to .pdf when the + // link is exported to PDF. The source document remains untouched. + ConvertOooTargetToPdfTarget bool + + // ExportLinksRelativeFsys specifies that the file system related + // hyperlinks (file:// protocol) present in the document will be exported + // as relative to the source document location. + ExportLinksRelativeFsys bool + + // ExportHiddenSlides exports, for LibreOffice Impress, slides that are not + // included in slide shows. + ExportHiddenSlides bool + + // SkipEmptyPages specifies that automatically inserted empty pages are + // suppressed. This option is active only if storing Writer documents. + SkipEmptyPages bool + + // AddOriginalDocumentAsStream specifies that a stream is inserted to the + // PDF file which contains the original document for archiving purposes. + AddOriginalDocumentAsStream bool + + // SinglePageSheets ignores each sheet’s paper size, print ranges and + // shown/hidden status and puts every sheet (even hidden sheets) on exactly + // one page. + SinglePageSheets bool + + // LosslessImageCompression specifies if images are exported to PDF using + // a lossless compression format like PNG or compressed using the JPEG + // format. LosslessImageCompression bool - // ReduceImageResolution allows turning on or off image resolution - // reduction to tweak image conversion performance. - // Optional + // Quality specifies the quality of the JPG export. A higher value produces + // a higher-quality image and a larger file. Between 1 and 90. + Quality int + + // ReduceImageResolution specifies if the resolution of each image is + // reduced to the resolution specified by the property MaxImageResolution. ReduceImageResolution bool + // MaxImageResolution, if the property ReduceImageResolution is set to + // true, tells if all images will be reduced to the given value in DPI. + // Possible values are: 75, 150, 300, 600 and 1200. + MaxImageResolution int + // PdfFormats allows to convert the resulting PDF to PDF/A-1b, PDF/A-2b, // PDF/A-3b and PDF/UA. - // Optional. PdfFormats gotenberg.PdfFormats } +// DefaultOptions returns the default values for Options. +func DefaultOptions() Options { + return Options{ + Landscape: false, + PageRanges: "", + ExportFormFields: true, + AllowDuplicateFieldNames: false, + ExportBookmarks: true, + ExportBookmarksToPdfDestination: false, + ExportPlaceholders: false, + ExportNotes: false, + ExportNotesPages: false, + ExportOnlyNotesPages: false, + ExportNotesInMargin: false, + ConvertOooTargetToPdfTarget: false, + ExportLinksRelativeFsys: false, + ExportHiddenSlides: false, + SkipEmptyPages: false, + AddOriginalDocumentAsStream: false, + SinglePageSheets: false, + LosslessImageCompression: false, + Quality: 90, + ReduceImageResolution: false, + MaxImageResolution: 300, + PdfFormats: gotenberg.PdfFormats{ + PdfA: "", + PdfUa: false, + }, + } +} + // 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 diff --git a/pkg/modules/libreoffice/api/api_test.go b/pkg/modules/libreoffice/api/api_test.go index eed96f97..faf6535c 100644 --- a/pkg/modules/libreoffice/api/api_test.go +++ b/pkg/modules/libreoffice/api/api_test.go @@ -14,6 +14,15 @@ import ( "github.com/gotenberg/gotenberg/v8/pkg/gotenberg" ) +func TestDefaultOptions(t *testing.T) { + actual := DefaultOptions() + notExpect := Options{} + + if reflect.DeepEqual(actual, notExpect) { + t.Errorf("expected %v and got identical %v", actual, notExpect) + } +} + func TestApi_Descriptor(t *testing.T) { descriptor := new(Api).Descriptor() diff --git a/pkg/modules/libreoffice/api/libreoffice.go b/pkg/modules/libreoffice/api/libreoffice.go index 1f8205d7..ccd94bed 100644 --- a/pkg/modules/libreoffice/api/libreoffice.go +++ b/pkg/modules/libreoffice/api/libreoffice.go @@ -273,25 +273,26 @@ func (p *libreOfficeProcess) pdf(ctx context.Context, logger *zap.Logger, inputP args = append(args, "--export", fmt.Sprintf("PageRange=%s", options.PageRanges)) } - if !options.ExportFormFields { - args = append(args, "--export", "ExportFormFields=false") - } - - if options.SinglePageSheets { - args = append(args, "--export", "SinglePageSheets=true") - } - - if options.ExportNotesInMargin { - args = append(args, "--export", "ExportNotesInMargin=true") - } - - if options.LosslessImageCompression { - args = append(args, "--export", "UseLosslessCompression=true") - } - - if !options.ReduceImageResolution { - args = append(args, "--export", "ReduceImageResolution=false") - } + args = append(args, "--export", fmt.Sprintf("ExportFormFields=%t", options.ExportFormFields)) + args = append(args, "--export", fmt.Sprintf("AllowDuplicateFieldNames=%t", options.AllowDuplicateFieldNames)) + args = append(args, "--export", fmt.Sprintf("ExportBookmarks=%t", options.ExportBookmarks)) + args = append(args, "--export", fmt.Sprintf("ExportBookmarks=%t", options.ExportBookmarks)) + args = append(args, "--export", fmt.Sprintf("ExportBookmarksToPDFDestination=%t", options.ExportBookmarksToPdfDestination)) + args = append(args, "--export", fmt.Sprintf("ExportPlaceholders=%t", options.ExportPlaceholders)) + args = append(args, "--export", fmt.Sprintf("ExportNotes=%t", options.ExportNotes)) + args = append(args, "--export", fmt.Sprintf("ExportNotesPages=%t", options.ExportNotesPages)) + args = append(args, "--export", fmt.Sprintf("ExportOnlyNotesPages=%t", options.ExportOnlyNotesPages)) + args = append(args, "--export", fmt.Sprintf("ExportNotesInMargin=%t", options.ExportNotesInMargin)) + args = append(args, "--export", fmt.Sprintf("ConvertOOoTargetToPDFTarget=%t", options.ConvertOooTargetToPdfTarget)) + args = append(args, "--export", fmt.Sprintf("ExportLinksRelativeFsys=%t", options.ExportLinksRelativeFsys)) + args = append(args, "--export", fmt.Sprintf("ExportHiddenSlides=%t", options.ExportHiddenSlides)) + args = append(args, "--export", fmt.Sprintf("IsSkipEmptyPages=%t", options.SkipEmptyPages)) + args = append(args, "--export", fmt.Sprintf("IsAddStream=%t", options.AddOriginalDocumentAsStream)) + args = append(args, "--export", fmt.Sprintf("SinglePageSheets=%t", options.SinglePageSheets)) + args = append(args, "--export", fmt.Sprintf("UseLosslessCompression=%t", options.LosslessImageCompression)) + args = append(args, "--export", fmt.Sprintf("Quality=%d", options.Quality)) + args = append(args, "--export", fmt.Sprintf("ReduceImageResolution=%t", options.ReduceImageResolution)) + args = append(args, "--export", fmt.Sprintf("MaxImageResolution=%d", options.MaxImageResolution)) switch options.PdfFormats.PdfA { case "": diff --git a/pkg/modules/libreoffice/api/libreoffice_test.go b/pkg/modules/libreoffice/api/libreoffice_test.go index 1c2a2639..a8de5048 100644 --- a/pkg/modules/libreoffice/api/libreoffice_test.go +++ b/pkg/modules/libreoffice/api/libreoffice_test.go @@ -336,7 +336,7 @@ func TestLibreOfficeProcess_pdf(t *testing.T) { expectError: false, }, { - scenario: "success (landscape)", + scenario: "success (not default options)", libreOffice: newLibreOfficeProcess( libreOfficeArguments{ binPath: os.Getenv("LIBREOFFICE_BIN_PATH"), @@ -352,188 +352,36 @@ func TestLibreOfficeProcess_pdf(t *testing.T) { t.Fatalf(fmt.Sprintf("expected no error but got: %v", err)) } - err = os.WriteFile(fmt.Sprintf("%s/document.txt", fs.WorkingDirPath()), []byte("Landscape"), 0o755) + err = os.WriteFile(fmt.Sprintf("%s/document.txt", fs.WorkingDirPath()), []byte("Success"), 0o755) if err != nil { t.Fatalf("expected no error but got: %v", err) } return fs }(), - options: Options{Landscape: true}, - cancelledCtx: false, - start: true, - expectError: false, - }, - { - scenario: "success (disable form fields)", - libreOffice: newLibreOfficeProcess( - libreOfficeArguments{ - binPath: os.Getenv("LIBREOFFICE_BIN_PATH"), - unoBinPath: os.Getenv("UNOCONVERTER_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("DisableFormFields"), 0o755) - if err != nil { - t.Fatalf("expected no error but got: %v", err) - } - - return fs - }(), - options: Options{ExportFormFields: false}, - cancelledCtx: false, - start: true, - expectError: false, - }, - { - scenario: "success (single page sheets)", - libreOffice: newLibreOfficeProcess( - libreOfficeArguments{ - binPath: os.Getenv("LIBREOFFICE_BIN_PATH"), - unoBinPath: os.Getenv("UNOCONVERTER_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("SinglePageSheets"), 0o755) - if err != nil { - t.Fatalf("expected no error but got: %v", err) - } - - return fs - }(), - options: Options{SinglePageSheets: true}, - cancelledCtx: false, - start: true, - expectError: false, - }, - { - scenario: "success (page ranges)", - libreOffice: newLibreOfficeProcess( - libreOfficeArguments{ - binPath: os.Getenv("LIBREOFFICE_BIN_PATH"), - unoBinPath: os.Getenv("UNOCONVERTER_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{PageRanges: "1-1"}, - cancelledCtx: false, - start: true, - expectError: false, - }, - { - scenario: "success ExportNotesInMargin", - libreOffice: newLibreOfficeProcess( - libreOfficeArguments{ - binPath: os.Getenv("LIBREOFFICE_BIN_PATH"), - unoBinPath: os.Getenv("UNOCONVERTER_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("ExportNotesInMargin"), 0o755) - if err != nil { - t.Fatalf("expected no error but got: %v", err) - } - - return fs - }(), - options: Options{ExportNotesInMargin: true}, - cancelledCtx: false, - start: true, - expectError: false, - }, - { - scenario: "success LosslessImageCompression", - libreOffice: newLibreOfficeProcess( - libreOfficeArguments{ - binPath: os.Getenv("LIBREOFFICE_BIN_PATH"), - unoBinPath: os.Getenv("UNOCONVERTER_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("LosslessImageCompression"), 0o755) - if err != nil { - t.Fatalf("expected no error but got: %v", err) - } - - return fs - }(), - options: Options{LosslessImageCompression: true}, - cancelledCtx: false, - start: true, - expectError: false, - }, - { - scenario: "success ReduceImageResolution", - libreOffice: newLibreOfficeProcess( - libreOfficeArguments{ - binPath: os.Getenv("LIBREOFFICE_BIN_PATH"), - unoBinPath: os.Getenv("UNOCONVERTER_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("ReduceImageResolution"), 0o755) - if err != nil { - t.Fatalf("expected no error but got: %v", err) - } - - return fs - }(), - options: Options{ReduceImageResolution: false}, + options: Options{ + Landscape: true, + PageRanges: "1", + ExportFormFields: false, + AllowDuplicateFieldNames: true, + ExportBookmarks: false, + ExportBookmarksToPdfDestination: true, + ExportPlaceholders: true, + ExportNotes: true, + ExportNotesPages: true, + ExportOnlyNotesPages: true, + ExportNotesInMargin: true, + ConvertOooTargetToPdfTarget: true, + ExportLinksRelativeFsys: true, + ExportHiddenSlides: true, + SkipEmptyPages: true, + AddOriginalDocumentAsStream: true, + SinglePageSheets: true, + LosslessImageCompression: true, + Quality: 100, + ReduceImageResolution: true, + MaxImageResolution: 600, + }, cancelledCtx: false, start: true, expectError: false, diff --git a/pkg/modules/libreoffice/routes.go b/pkg/modules/libreoffice/routes.go index 8441b477..1dde35f7 100644 --- a/pkg/modules/libreoffice/routes.go +++ b/pkg/modules/libreoffice/routes.go @@ -5,6 +5,8 @@ import ( "errors" "fmt" "net/http" + "slices" + "strconv" "github.com/labstack/echo/v4" @@ -22,33 +24,100 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap IsMultipart: true, Handler: func(c echo.Context) error { ctx := c.Get("context").(*api.Context) + defaultOptions := libreofficeapi.DefaultOptions() // Let's get the data from the form and validate them. var ( - inputPaths []string - landscape bool - nativePageRanges string - exportFormFields bool - singlePageSheets bool - exportNotesInMargin bool - losslessImageCompression bool - reduceImageResolution bool - pdfa string - pdfua bool - nativePdfFormats bool - merge bool - metadata map[string]interface{} + inputPaths []string + landscape bool + nativePageRanges string + exportFormFields bool + allowDuplicateFieldNames bool + exportBookmarks bool + exportBookmarksToPdfDestination bool + exportPlaceholders bool + exportNotes bool + exportNotesPages bool + exportOnlyNotesPages bool + exportNotesInMargin bool + convertOooTargetToPdfTarget bool + exportLinksRelativeFsys bool + exportHiddenSlides bool + skipEmptyPages bool + addOriginalDocumentAsStream bool + singlePageSheets bool + losslessImageCompression bool + quality int + reduceImageResolution bool + maxImageResolution int + pdfa string + pdfua bool + nativePdfFormats bool + merge bool + metadata map[string]interface{} ) err := ctx.FormData(). MandatoryPaths(libreOffice.Extensions(), &inputPaths). - Bool("landscape", &landscape, false). - String("nativePageRanges", &nativePageRanges, ""). - Bool("exportFormFields", &exportFormFields, true). - Bool("singlePageSheets", &singlePageSheets, false). - Bool("exportNotesInMargin", &exportNotesInMargin, false). - Bool("losslessImageCompression", &losslessImageCompression, false). - Bool("reduceImageResolution", &reduceImageResolution, true). + Bool("landscape", &landscape, defaultOptions.Landscape). + String("nativePageRanges", &nativePageRanges, defaultOptions.PageRanges). + Bool("exportFormFields", &exportFormFields, defaultOptions.ExportFormFields). + Bool("allowDuplicateFieldNames", &allowDuplicateFieldNames, defaultOptions.AllowDuplicateFieldNames). + Bool("exportBookmarks", &exportBookmarks, defaultOptions.ExportBookmarks). + Bool("exportBookmarksToPdfDestination", &exportBookmarksToPdfDestination, defaultOptions.ExportBookmarksToPdfDestination). + Bool("exportPlaceholders", &exportPlaceholders, defaultOptions.ExportPlaceholders). + Bool("exportNotes", &exportNotes, defaultOptions.ExportNotes). + Bool("exportNotesPages", &exportNotesPages, defaultOptions.ExportNotesPages). + Bool("exportOnlyNotesPages", &exportOnlyNotesPages, defaultOptions.ExportOnlyNotesPages). + Bool("exportNotesInMargin", &exportNotesInMargin, defaultOptions.ExportNotesInMargin). + Bool("convertOooTargetToPdfTarget", &convertOooTargetToPdfTarget, defaultOptions.ConvertOooTargetToPdfTarget). + Bool("exportLinksRelativeFsys", &exportLinksRelativeFsys, defaultOptions.ExportLinksRelativeFsys). + Bool("exportHiddenSlides", &exportHiddenSlides, defaultOptions.ExportHiddenSlides). + Bool("skipEmptyPages", &skipEmptyPages, defaultOptions.SkipEmptyPages). + Bool("addOriginalDocumentAsStream", &addOriginalDocumentAsStream, defaultOptions.AddOriginalDocumentAsStream). + Bool("singlePageSheets", &singlePageSheets, defaultOptions.SinglePageSheets). + Bool("losslessImageCompression", &losslessImageCompression, defaultOptions.LosslessImageCompression). + Custom("quality", func(value string) error { + if value == "" { + quality = defaultOptions.Quality + return nil + } + + intValue, err := strconv.Atoi(value) + if err != nil { + return err + } + + if intValue < 1 { + return errors.New("value is inferior to 1") + } + + if intValue > 100 { + return errors.New("value is superior to 100") + } + + quality = intValue + return nil + }). + Bool("reduceImageResolution", &reduceImageResolution, defaultOptions.ReduceImageResolution). + Custom("maxImageResolution", func(value string) error { + if value == "" { + maxImageResolution = defaultOptions.MaxImageResolution + return nil + } + + intValue, err := strconv.Atoi(value) + if err != nil { + return err + } + + if !slices.Contains([]int{75, 150, 300, 600, 1200}, intValue) { + return errors.New("value is not 75, 150, 300, 600 or 1200") + } + + maxImageResolution = intValue + return nil + }). String("pdfa", &pdfa, ""). Bool("pdfua", &pdfua, false). Bool("nativePdfFormats", &nativePdfFormats, true). @@ -77,13 +146,27 @@ func convertRoute(libreOffice libreofficeapi.Uno, engine gotenberg.PdfEngine) ap for i, inputPath := range inputPaths { outputPaths[i] = ctx.GeneratePath(".pdf") options := libreofficeapi.Options{ - Landscape: landscape, - PageRanges: nativePageRanges, - ExportFormFields: exportFormFields, - SinglePageSheets: singlePageSheets, - ExportNotesInMargin: exportNotesInMargin, - LosslessImageCompression: losslessImageCompression, - ReduceImageResolution: reduceImageResolution, + Landscape: landscape, + PageRanges: nativePageRanges, + ExportFormFields: exportFormFields, + AllowDuplicateFieldNames: allowDuplicateFieldNames, + ExportBookmarks: exportBookmarks, + ExportBookmarksToPdfDestination: exportBookmarksToPdfDestination, + ExportPlaceholders: exportPlaceholders, + ExportNotes: exportNotes, + ExportNotesPages: exportNotesPages, + ExportOnlyNotesPages: exportOnlyNotesPages, + ExportNotesInMargin: exportNotesInMargin, + ConvertOooTargetToPdfTarget: convertOooTargetToPdfTarget, + ExportLinksRelativeFsys: exportLinksRelativeFsys, + ExportHiddenSlides: exportHiddenSlides, + SkipEmptyPages: skipEmptyPages, + AddOriginalDocumentAsStream: addOriginalDocumentAsStream, + SinglePageSheets: singlePageSheets, + LosslessImageCompression: losslessImageCompression, + Quality: quality, + ReduceImageResolution: reduceImageResolution, + MaxImageResolution: maxImageResolution, } if nativePdfFormats { diff --git a/pkg/modules/libreoffice/routes_test.go b/pkg/modules/libreoffice/routes_test.go index 1455569a..56af4734 100644 --- a/pkg/modules/libreoffice/routes_test.go +++ b/pkg/modules/libreoffice/routes_test.go @@ -39,6 +39,116 @@ func TestConvertRoute(t *testing.T) { expectHttpStatus: http.StatusBadRequest, expectOutputPathsCount: 0, }, + { + scenario: "invalid quality form field (not an integer)", + 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{ + "quality": { + "foo", + }, + }) + return ctx + }(), + libreOffice: &libreofficeapi.ApiMock{ExtensionsMock: func() []string { + return []string{".docx"} + }}, + expectError: true, + expectHttpError: true, + expectHttpStatus: http.StatusBadRequest, + expectOutputPathsCount: 0, + }, + { + scenario: "invalid quality form field (< 1)", + 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{ + "quality": { + "0", + }, + }) + return ctx + }(), + libreOffice: &libreofficeapi.ApiMock{ExtensionsMock: func() []string { + return []string{".docx"} + }}, + expectError: true, + expectHttpError: true, + expectHttpStatus: http.StatusBadRequest, + expectOutputPathsCount: 0, + }, + { + scenario: "invalid quality form field (> 100)", + 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{ + "quality": { + "101", + }, + }) + return ctx + }(), + libreOffice: &libreofficeapi.ApiMock{ExtensionsMock: func() []string { + return []string{".docx"} + }}, + expectError: true, + expectHttpError: true, + expectHttpStatus: http.StatusBadRequest, + expectOutputPathsCount: 0, + }, + { + scenario: "invalid maxImageResolution form field (not an integer)", + 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{ + "maxImageResolution": { + "foo", + }, + }) + return ctx + }(), + libreOffice: &libreofficeapi.ApiMock{ExtensionsMock: func() []string { + return []string{".docx"} + }}, + expectError: true, + expectHttpError: true, + expectHttpStatus: http.StatusBadRequest, + expectOutputPathsCount: 0, + }, + { + scenario: "invalid maxImageResolution form field (not in range)", + 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{ + "maxImageResolution": { + "1", + }, + }) + return ctx + }(), + libreOffice: &libreofficeapi.ApiMock{ExtensionsMock: func() []string { + return []string{".docx"} + }}, + expectError: true, + expectHttpError: true, + expectHttpStatus: http.StatusBadRequest, + expectOutputPathsCount: 0, + }, { scenario: "invalid metadata form field", ctx: func() *api.ContextMock { @@ -285,6 +395,12 @@ func TestConvertRoute(t *testing.T) { "document2.docx": "/document2.docx", }) ctx.SetValues(map[string][]string{ + "quality": { + "100", + }, + "maxImageResolution": { + "1200", + }, "merge": { "true", },