aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSam Anthony <sam@samanthony.xyz>2026-05-13 15:47:33 -0400
committerSam Anthony <sam@samanthony.xyz>2026-05-13 15:47:33 -0400
commit48f85453ffbe36f6c428a5d9a23b74122686b64c (patch)
tree13720a581029307fd9303f025d9cd8c1012261b3
parent66ef9438a3489bf8a0b80bb44e320c85261a6658 (diff)
downloadlulu-48f85453ffbe36f6c428a5d9a23b74122686b64c.zip
test marshal print and reprint requests
-rw-r--r--lulu.go4
-rw-r--r--print.go22
-rw-r--r--print_test.go42
-rw-r--r--ship.go2
-rw-r--r--testdata/printreq.json31
-rw-r--r--testdata/reprintreq.json29
6 files changed, 124 insertions, 6 deletions
diff --git a/lulu.go b/lulu.go
index 2268cd1..04e34ab 100644
--- a/lulu.go
+++ b/lulu.go
@@ -241,8 +241,7 @@ func (c *Client) Print(contact EmailAddress, externalId string, productionDelay
if err := verifyProductionDelay(productionDelay); err != nil {
return PrintJob{}, pkgErr(err)
}
-
- req := printReq{
+ req := printReq[Printable]{
Contact: contact,
ExternalId: externalId,
LineItems: items,
@@ -250,7 +249,6 @@ func (c *Client) Print(contact EmailAddress, externalId string, productionDelay
ShipAddr: addr,
ShipOpt: shipOpt,
}
-
var job PrintJob
err := c.postDecode(printJobsPath, req, http.StatusCreated, &job)
if err != nil {
diff --git a/print.go b/print.go
index 8532fff..22880ed 100644
--- a/print.go
+++ b/print.go
@@ -11,10 +11,10 @@ const (
MaxProductionDelay = 48 * time.Hour
)
-type printReq struct {
+type printReq[P Printable | Reprintable] struct {
Contact EmailAddress `json:"contact_email"`
ExternalId string `json:"external_id"`
- LineItems []Printable `json:"line_items"`
+ LineItems []P `json:"line_items"`
ProductionDelayMins uint `json:"production_delay"`
ShipAddr ShippingAddress `json:"shipping_address"`
ShipOpt ShippingLevel `json:"shipping_level"`
@@ -52,6 +52,24 @@ type Printable struct {
Title string `json:"title"`
}
+// Reprintable is a printable whose PrintableId is known from an prior
+// print job.
+type Reprintable struct {
+ // Arbitrary string to identify and connect a print job to your
+ // systems. Set it to an order number, a purchase order or
+ // whatever else works for your particular use case.
+ ExternalId string `json:"external_id"`
+
+ // Uniquely identifies the printable.
+ PrintableId PrintableId `json:"printable_id"`
+
+ // The number of copies to print.
+ Quantity uint `json:"quantity"`
+
+ // The title of the book. Must not exceed 255 bytes.
+ Title string `json:"title"`
+}
+
type getPrintJobsResp struct {
Count uint `json:"count"`
Next string `json:"next"`
diff --git a/print_test.go b/print_test.go
index ec4e455..ce9fbda 100644
--- a/print_test.go
+++ b/print_test.go
@@ -101,6 +101,48 @@ func TestGetPrintJobs(t *testing.T) {
require.NoError(t, err)
}
+//go:embed testdata/printreq.json
+var printReqJson string
+
+func TestMarshalPrintReq(t *testing.T) {
+ req := printReq[Printable]{
+ Contact: MustParseEmailAddress("test@test.com"),
+ ExternalId: "demo-time",
+ LineItems: []Printable{{
+ ExternalId: "item-reference-1",
+ CoverUrl: "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1",
+ InteriorUrl: "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1",
+ Mfg: PkgId{UsTrade, Mono, Standard, Perfect, P60UncoatedWhite, Matte, NoLinen, NoFoil},
+ Quantity: 30,
+ Title: "My Book",
+ }},
+ ProductionDelayMins: 120,
+ ShipAddr: shipAddrSample,
+ ShipOpt: Mail,
+ }
+ requireMarshalJsonEq(t, printReqJson, req)
+}
+
+//go:embed testdata/reprintreq.json
+var reprintReqJson string
+
+func TestMarshalReprintReq(t *testing.T) {
+ req := printReq[Reprintable]{
+ Contact: MustParseEmailAddress("test@test.com"),
+ ExternalId: "demo-time",
+ LineItems: []Reprintable{{
+ ExternalId: "item-reference-1",
+ PrintableId: PrintableId("11606ab3-9355-46d3-ae90-338db6f5d271"),
+ Quantity: 30,
+ Title: "My Book",
+ }},
+ ProductionDelayMins: 120,
+ ShipAddr: shipAddrSample,
+ ShipOpt: Mail,
+ }
+ requireMarshalJsonEq(t, reprintReqJson, req)
+}
+
func TestPrint(t *testing.T) {
contact := MustParseEmailAddress("test@test.com")
jobEid := "demo-time"
diff --git a/ship.go b/ship.go
index 030c80d..0f59222 100644
--- a/ship.go
+++ b/ship.go
@@ -35,7 +35,7 @@ type ShippingAddress struct {
// 2 or 3 letter state code (officially called ISO-3166-2
// subdivision codes). They are required for some countries (e.g.
// US, MX, CA, AU).
- State string `json:"state"`
+ State string `json:"state_code"`
City string `json:"city"`
Street1 string `json:"street1"` // First address line
diff --git a/testdata/printreq.json b/testdata/printreq.json
new file mode 100644
index 0000000..c1bde40
--- /dev/null
+++ b/testdata/printreq.json
@@ -0,0 +1,31 @@
+{
+ "contact_email": "test@test.com",
+ "external_id": "demo-time",
+ "line_items": [
+ {
+ "external_id": "item-reference-1",
+ "cover": "https://www.dropbox.com/s/7bv6mg2tj0h3l0r/lulu_trade_perfect_template.pdf?dl=1&raw=1",
+ "interior": "https://www.dropbox.com/s/r20orb8umqjzav9/lulu_trade_interior_template-32.pdf?dl=1&raw=1",
+ "pod_package_id": "0600X0900.BW.STD.PB.060UW444.MXX",
+ "quantity": 30,
+ "title": "My Book"
+ }
+ ],
+ "production_delay": 120,
+ "shipping_address": {
+ "city": "Lübeck",
+ "country_code": "DE",
+ "name": "Hans Dampf",
+ "phone_number": "844-212-0689",
+ "postcode": "23552",
+ "state_code": "",
+ "street1": "Holstenstr. 40",
+ "street2": "",
+ "email": "",
+ "title": "",
+ "is_business": false,
+ "organization": "",
+ "recipient_tax_id": ""
+ },
+ "shipping_level": "MAIL"
+}
diff --git a/testdata/reprintreq.json b/testdata/reprintreq.json
new file mode 100644
index 0000000..75544cd
--- /dev/null
+++ b/testdata/reprintreq.json
@@ -0,0 +1,29 @@
+{
+ "contact_email": "test@test.com",
+ "external_id": "demo-time",
+ "line_items": [
+ {
+ "external_id": "item-reference-1",
+ "printable_id": "11606ab3-9355-46d3-ae90-338db6f5d271",
+ "quantity": 30,
+ "title": "My Book"
+ }
+ ],
+ "production_delay": 120,
+ "shipping_address": {
+ "city": "Lübeck",
+ "country_code": "DE",
+ "name": "Hans Dampf",
+ "phone_number": "844-212-0689",
+ "postcode": "23552",
+ "state_code": "",
+ "street1": "Holstenstr. 40",
+ "street2": "",
+ "email": "",
+ "title": "",
+ "is_business": false,
+ "organization": "",
+ "recipient_tax_id": ""
+ },
+ "shipping_level": "MAIL"
+}