feat(pdfengines): redesign Factur-X API with dedicated form fields

This commit is contained in:
Julien Neuhart
2026-06-06 14:03:58 +02:00
parent 9ab39b6fca
commit 287ee5be72
23 changed files with 599 additions and 253 deletions

View File

@@ -7,8 +7,6 @@ import (
"reflect"
"testing"
"time"
"github.com/gotenberg/gotenberg/v8/pkg/gotenberg"
)
func TestFormData_Validate(t *testing.T) {
@@ -1786,110 +1784,56 @@ func TestFormData_Embeds(t *testing.T) {
}
}
func TestFormData_FacturX(t *testing.T) {
func TestFormData_FacturXXml(t *testing.T) {
for _, tc := range []struct {
scenario string
form *FormData
mandatory bool
expect gotenberg.FacturX
expectErr bool
scenario string
form *FormData
expect string
}{
{
scenario: "key does not exist, not mandatory",
form: &FormData{},
mandatory: false,
expect: gotenberg.FacturX{},
scenario: "no facturxXml file",
form: &FormData{},
expect: "",
},
{
scenario: "key does not exist, mandatory",
form: &FormData{},
mandatory: true,
expectErr: true,
},
{
scenario: "all fields provided",
scenario: "facturxXml file present",
form: &FormData{
values: map[string][]string{
"facturx": {`{"conformanceLevel":"EXTENDED","documentType":"ORDER","documentFileName":"order.xml","version":"2.0"}`},
filesByField: map[string][]string{
FacturXXmlFormField: {"/tmp/abc/12345.xml"},
},
},
expect: gotenberg.FacturX{
ConformanceLevel: gotenberg.FacturXConformanceExtended,
DocumentType: gotenberg.FacturXDocumentTypeOrder,
DocumentFileName: "order.xml",
Version: "2.0",
},
},
{
scenario: "only conformance level, defaults applied",
form: &FormData{
values: map[string][]string{
"facturx": {`{"conformanceLevel":"EN 16931"}`},
},
},
expect: gotenberg.FacturX{
ConformanceLevel: gotenberg.FacturXConformanceEN16931,
DocumentType: gotenberg.FacturXDocumentTypeInvoice,
DocumentFileName: "factur-x.xml",
Version: "1.0",
},
},
{
scenario: "invalid JSON",
form: &FormData{
values: map[string][]string{
"facturx": {`{not json`},
},
},
expectErr: true,
},
{
scenario: "missing conformance level",
form: &FormData{
values: map[string][]string{
"facturx": {`{"documentType":"INVOICE"}`},
},
},
expectErr: true,
},
{
scenario: "unsupported conformance level",
form: &FormData{
values: map[string][]string{
"facturx": {`{"conformanceLevel":"FOO"}`},
},
},
expectErr: true,
},
{
scenario: "unsupported document type",
form: &FormData{
values: map[string][]string{
"facturx": {`{"conformanceLevel":"BASIC","documentType":"RECEIPT"}`},
},
},
expectErr: true,
expect: "/tmp/abc/12345.xml",
},
} {
t.Run(tc.scenario, func(t *testing.T) {
var actual gotenberg.FacturX
var actual string
tc.form.FacturX(&actual, tc.mandatory)
tc.form.FacturXXml(&actual)
if tc.expectErr {
if tc.form.errors == nil {
t.Error("expected an error but got none")
}
return
}
if tc.form.errors != nil {
t.Errorf("expected no error but got: %v", tc.form.errors)
}
if !reflect.DeepEqual(actual, tc.expect) {
t.Errorf("expected %+v but got %+v", tc.expect, actual)
if actual != tc.expect {
t.Errorf("expected %q but got %q", tc.expect, actual)
}
})
}
}
// TestFormData_paths_excludesFacturXXml verifies that an uploaded facturxXml is
// never picked up as an input document by paths().
func TestFormData_paths_excludesFacturXXml(t *testing.T) {
form := &FormData{
files: map[string]string{
"document.xml": "/tmp/abc/document.xml",
"factur-x.xml": "/tmp/abc/invoice.xml",
},
filesByField: map[string][]string{
FacturXXmlFormField: {"/tmp/abc/invoice.xml"},
},
}
var paths []string
form.paths([]string{".xml"}, &paths)
if len(paths) != 1 || paths[0] != "/tmp/abc/document.xml" {
t.Errorf("expected only the non-Factur-X .xml document, got %+v", paths)
}
}