aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--cover.go55
-rw-r--r--cover_test.go57
-rw-r--r--interior.go45
-rw-r--r--interior_test.go122
-rw-r--r--lulu.go87
-rw-r--r--lulu_test.go165
7 files changed, 280 insertions, 253 deletions
diff --git a/Makefile b/Makefile
index 8c3ea98..59689ef 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-GEN = pkgid_gen.go
+GEN = $(addsuffix _gen.go, cover interior pkgid)
TEST = $(wildcard *_test.go)
SRC = $(filter-out ${GEN} ${TEST}, $(wildcard *.go))
diff --git a/cover.go b/cover.go
new file mode 100644
index 0000000..30be2d6
--- /dev/null
+++ b/cover.go
@@ -0,0 +1,55 @@
+package lulu
+
+import (
+ "encoding/json"
+ "fmt"
+ "strconv"
+)
+
+//go:generate go run github.com/yawnak/string-enumer -t Unit --text -o ./cover_gen.go .
+
+// Unit is a unit of length measurement.
+type Unit string
+
+const (
+ Points Unit = "pt"
+ Millimeters Unit = "mm"
+ Inches Unit = "inch"
+)
+
+// coverDimensionsReq is the json body of a /cover-dimensions/ request.
+type coverDimensionsReq struct {
+ PkgId PkgId `json:"pod_package_id"`
+ NPages uint `json:"interior_page_count"`
+ Unit Unit `json:"unit"`
+}
+
+type CoverDimensions struct {
+ Width, Height float64
+ Unit Unit
+}
+
+func (cd *CoverDimensions) UnmarshalJSON(data []byte) error {
+ s := string(data)
+ var alias struct {
+ Width, Height string
+ Unit Unit
+ }
+ if err := json.Unmarshal(data, &alias); err != nil {
+ return fmt.Errorf("malformed %T: %q: %w", cd, s, err)
+ }
+
+ w, err := strconv.ParseFloat(alias.Width, 64)
+ if err != nil {
+ return fmt.Errorf("malformed %T.Width: %q: %w", cd, s, err)
+ }
+ h, err := strconv.ParseFloat(alias.Height, 64)
+ if err != nil {
+ return fmt.Errorf("malformed %T.Height: %q: %w", cd, s, err)
+ }
+
+ cd.Width = w
+ cd.Height = h
+ cd.Unit = alias.Unit
+ return nil
+}
diff --git a/cover_test.go b/cover_test.go
new file mode 100644
index 0000000..a0042c1
--- /dev/null
+++ b/cover_test.go
@@ -0,0 +1,57 @@
+package lulu
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestMarshalCoverDimensionsReq(t *testing.T) {
+ t.Parallel()
+ requireMarshalJsonEq(t, `{
+ "pod_package_id": "0600X0900.BW.STD.PB.060UW444.MXX",
+ "interior_page_count": 210,
+ "unit": "pt"}`,
+ coverDimensionsReq{
+ PkgId{
+ UsTrade,
+ Mono,
+ Standard,
+ Perfect,
+ P60UncoatedWhite,
+ Matte,
+ NoLinen,
+ NoFoil},
+ 210,
+ Points})
+}
+
+func TestUnmarshalCoverDimensions(t *testing.T) {
+ t.Parallel()
+ requireUnmarshalJsonEq(t,
+ CoverDimensions{123.4, 567.8, Points},
+ `{"width": "123.400", "height": "567.800", "unit": "pt"}`)
+ requireUnmarshalJsonEq(t,
+ CoverDimensions{123.4, 567.8, Millimeters},
+ `{"width": "123.400", "height": "567.800", "unit": "mm"}`)
+ requireUnmarshalJsonEq(t,
+ CoverDimensions{123.4, 567.8, Inches},
+ `{"width": "123.400", "height": "567.800", "unit": "inch"}`)
+}
+
+func TestCoverDimensions(t *testing.T) {
+ c := newClient(t)
+ mfg := PkgId{
+ UsTrade,
+ Mono,
+ Standard,
+ Perfect,
+ P60UncoatedWhite,
+ Matte,
+ NoLinen,
+ NoFoil,
+ }
+ dims, err := c.CoverDimensions(mfg, 210, Points)
+ require.NoError(t, err)
+ require.Equal(t, CoverDimensions{920, 666, Points}, dims)
+}
diff --git a/interior.go b/interior.go
new file mode 100644
index 0000000..19417e5
--- /dev/null
+++ b/interior.go
@@ -0,0 +1,45 @@
+package lulu
+
+//go:generate go run github.com/yawnak/string-enumer -t InteriorValidationStatus --text -o ./interior_gen.go .
+
+// InteriorValidationStatus is the status of a validation job for an
+// interior file that is running on the server.
+type InteriorValidationStatus string
+
+const (
+ InteriorStatusNull InteriorValidationStatus = "NULL" // file validation is not started yet
+ InteriorStatusValidating InteriorValidationStatus = "VALIDATING" // file validation is still running
+ InteriorStatusValidated InteriorValidationStatus = "VALIDATED" // file validation finished without any errors
+ InteriorStatusNormalizing InteriorValidationStatus = "NORMALIZING" // file normalization (next step of validation, available only if pod_package_id is was passed in the payload) is still running
+ InteriorStatusNormalized InteriorValidationStatus = "NORMALIZED" // file normalization finished without any errors
+ InteriorStatusError InteriorValidationStatus = "ERROR" // file is invalid, list of errors is included in the response
+)
+
+func (s InteriorValidationStatus) IsFinal() bool {
+ switch s {
+ case InteriorStatusValidated, InteriorStatusNormalized, InteriorStatusError:
+ return true
+ }
+ return false
+}
+
+// validateInteriorReq is the json body of a /validate-interior/ request.
+type validateInteriorReq struct {
+ SrcUrl string `json:"source_url"`
+ PkgId PkgId `json:"pod_package_id"`
+}
+
+// validateInteriorReq is the json body of a /validate-interior/ request without the optional pod_package_id.
+type validateInteriorBasicReq struct {
+ SrcUrl string `json:"source_url"`
+}
+
+// InteriorValidationRecord contains the validation status of an interior file.
+type InteriorValidationRecord struct {
+ Id uint
+ SrcUrl string `json:"source_url"`
+ NPages uint `json:"page_count"`
+ Errors string
+ Status InteriorValidationStatus
+ ValidPkgIds []PkgId `json:"valid_pod_package_ids"`
+}
diff --git a/interior_test.go b/interior_test.go
new file mode 100644
index 0000000..ba3d948
--- /dev/null
+++ b/interior_test.go
@@ -0,0 +1,122 @@
+package lulu
+
+import (
+ "context"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+)
+
+func TestMarshalValidateInteriorReq(t *testing.T) {
+ t.Parallel()
+ want := `{
+ "source_url": "https://example.com/interior.pdf",
+ "pod_package_id": "0850X1100.BW.STD.LW.060UW444.MNG"
+}`
+ req := validateInteriorReq{
+ "https://example.com/interior.pdf",
+ PkgId{
+ UsLetter,
+ Mono,
+ Standard,
+ LinenWrap,
+ P60UncoatedWhite,
+ Matte,
+ NavyLinen,
+ GoldFoil},
+ }
+ requireMarshalJsonEq(t, want, req)
+}
+
+func TestMarshalValidateInteriorBasicReq(t *testing.T) {
+ t.Parallel()
+ requireMarshalJsonEq(t,
+ `{"source_url": "https://example.com/interior.pdf"}`,
+ validateInteriorBasicReq{"https://example.com/interior.pdf"})
+}
+
+func TestUnmarshalInteriorValidationRecord(t *testing.T) {
+ t.Parallel()
+ data := `{
+ "id": 1,
+ "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1",
+ "page_count": 210,
+ "errors": null,
+ "status": "VALIDATING",
+ "valid_pod_package_ids": null
+}`
+ want := InteriorValidationRecord{
+ 1,
+ "https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1",
+ 210,
+ "",
+ InteriorStatusValidating,
+ nil,
+ }
+ requireUnmarshalJsonEq(t, want, data)
+}
+
+func TestValidateInterior(t *testing.T) {
+ c := newClient(t)
+ mfg := PkgId{
+ UsTrade,
+ Mono,
+ Standard,
+ Perfect,
+ P60UncoatedWhite,
+ Gloss,
+ NoLinen,
+ NoFoil,
+ }
+ id, err := c.ValidateInterior(interiorUrl, mfg)
+ require.NoError(t, err)
+ require.NotZero(t, id)
+ // It seems the server doesn't populate most of the response
+ // fields, but we just need the ID anyway.
+}
+
+func TestValidateInteriorBasic(t *testing.T) {
+ c := newClient(t)
+ id, err := c.ValidateInteriorBasic(interiorUrl)
+ require.NoError(t, err)
+ require.NotZero(t, id)
+ // It seems the server doesn't populate most of the response
+ // fields, but we just need the ID anyway.
+}
+
+func TestGetInteriorValidation(t *testing.T) {
+ c := newClient(t)
+
+ // Start validation job
+ id, err := c.ValidateInteriorBasic(interiorUrl)
+ require.NoError(t, err)
+
+ // Poll until done
+ timeout := 15 * time.Second
+ period := time.Second
+ ctx, cancel := context.WithTimeout(context.Background(), timeout)
+ defer cancel()
+ timer := time.NewTimer(period)
+ for {
+ select {
+ case <-timer.C:
+ rec, err := c.GetInteriorValidation(id)
+ require.NoError(t, err)
+ if rec.Status.IsFinal() {
+ require.Equal(t, InteriorStatusValidated, rec.Status)
+
+ require.Equal(t, id, rec.Id)
+ require.Equal(t, interiorUrl, rec.SrcUrl)
+ require.Equal(t, uint(210), rec.NPages)
+ require.Empty(t, rec.Errors)
+ require.NotEmpty(t, rec.ValidPkgIds)
+ return
+ }
+ timer.Reset(period)
+ case <-ctx.Done():
+ t.Errorf("status still not finalized after %v", timeout)
+ return
+ }
+ }
+}
diff --git a/lulu.go b/lulu.go
index af425f0..1fdf7a3 100644
--- a/lulu.go
+++ b/lulu.go
@@ -9,7 +9,6 @@ import (
"io"
"net/http"
"net/url"
- "strconv"
"golang.org/x/oauth2/clientcredentials"
)
@@ -29,92 +28,6 @@ const (
// you are ready to deploy.
var ApiUrl = SandboxUrl
-// Unit is a unit of length measurement.
-type Unit string
-
-const (
- Points Unit = "pt"
- Millimeters Unit = "mm"
- Inches Unit = "inch"
-)
-
-type ValidationStatus string
-
-const (
- StatusNull ValidationStatus = "NULL" // file validation is not started yet
- StatusValidating ValidationStatus = "VALIDATING" // file validation is still running
- StatusValidated ValidationStatus = "VALIDATED" // file validation finished without any errors
- StatusNormalizing ValidationStatus = "NORMALIZING" // file normalization (next step of validation, available only if pod_package_id is was passed in the payload) is still running
- StatusNormalized ValidationStatus = "NORMALIZED" // file normalization finished without any errors
- StatusError ValidationStatus = "ERROR" // file is invalid, list of errors is included in the response
-)
-
-func (s ValidationStatus) IsFinal() bool {
- switch s {
- case StatusValidated, StatusNormalized, StatusError:
- return true
- }
- return false
-}
-
-// validateInteriorReq is the json body of a /validate-interior/ request.
-type validateInteriorReq struct {
- SrcUrl string `json:"source_url"`
- PkgId PkgId `json:"pod_package_id"`
-}
-
-// validateInteriorReq is the json body of a /validate-interior/ request without the optional pod_package_id.
-type validateInteriorBasicReq struct {
- SrcUrl string `json:"source_url"`
-}
-
-// InteriorValidationRecord contains the validation status of an interior file.
-type InteriorValidationRecord struct {
- Id uint
- SrcUrl string `json:"source_url"`
- NPages uint `json:"page_count"`
- Errors string
- Status ValidationStatus
- ValidPkgIds []PkgId `json:"valid_pod_package_ids"`
-}
-
-// coverDimensionsReq is the json body of a /cover-dimensions/ request.
-type coverDimensionsReq struct {
- PkgId PkgId `json:"pod_package_id"`
- NPages uint `json:"interior_page_count"`
- Unit Unit `json:"unit"`
-}
-
-type CoverDimensions struct {
- Width, Height float64
- Unit Unit
-}
-
-func (cd *CoverDimensions) UnmarshalJSON(data []byte) error {
- s := string(data)
- var alias struct {
- Width, Height string
- Unit Unit
- }
- if err := json.Unmarshal(data, &alias); err != nil {
- return fmt.Errorf("malformed %T: %q: %w", cd, s, err)
- }
-
- w, err := strconv.ParseFloat(alias.Width, 64)
- if err != nil {
- return fmt.Errorf("malformed %T.Width: %q: %w", cd, s, err)
- }
- h, err := strconv.ParseFloat(alias.Height, 64)
- if err != nil {
- return fmt.Errorf("malformed %T.Height: %q: %w", cd, s, err)
- }
-
- cd.Width = w
- cd.Height = h
- cd.Unit = alias.Unit
- return nil
-}
-
type Client struct {
c *http.Client
}
diff --git a/lulu_test.go b/lulu_test.go
index 513d590..05d37ad 100644
--- a/lulu_test.go
+++ b/lulu_test.go
@@ -1,13 +1,11 @@
package lulu
import (
- "context"
"encoding/json"
"fmt"
"os"
"strings"
"testing"
- "time"
"github.com/stretchr/testify/require"
)
@@ -44,169 +42,6 @@ func TestMain(m *testing.M) {
m.Run()
}
-func TestMarshalValidateInteriorReq(t *testing.T) {
- t.Parallel()
- want := `{
- "source_url": "https://example.com/interior.pdf",
- "pod_package_id": "0850X1100.BW.STD.LW.060UW444.MNG"
-}`
- req := validateInteriorReq{
- "https://example.com/interior.pdf",
- PkgId{
- UsLetter,
- Mono,
- Standard,
- LinenWrap,
- P60UncoatedWhite,
- Matte,
- NavyLinen,
- GoldFoil},
- }
- requireMarshalJsonEq(t, want, req)
-}
-
-func TestMarshalValidateInteriorBasicReq(t *testing.T) {
- t.Parallel()
- requireMarshalJsonEq(t,
- `{"source_url": "https://example.com/interior.pdf"}`,
- validateInteriorBasicReq{"https://example.com/interior.pdf"})
-}
-
-func TestUnmarshalInteriorValidationRecord(t *testing.T) {
- t.Parallel()
- data := `{
- "id": 1,
- "source_url": "https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1",
- "page_count": 210,
- "errors": null,
- "status": "VALIDATING",
- "valid_pod_package_ids": null
-}`
- want := InteriorValidationRecord{
- 1,
- "https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1",
- 210,
- "",
- StatusValidating,
- nil,
- }
- requireUnmarshalJsonEq(t, want, data)
-}
-
-func TestValidateInterior(t *testing.T) {
- c := newClient(t)
- mfg := PkgId{
- UsTrade,
- Mono,
- Standard,
- Perfect,
- P60UncoatedWhite,
- Gloss,
- NoLinen,
- NoFoil,
- }
- id, err := c.ValidateInterior(interiorUrl, mfg)
- require.NoError(t, err)
- require.NotZero(t, id)
- // It seems the server doesn't populate most of the response
- // fields, but we just need the ID anyway.
-}
-
-func TestValidateInteriorBasic(t *testing.T) {
- c := newClient(t)
- id, err := c.ValidateInteriorBasic(interiorUrl)
- require.NoError(t, err)
- require.NotZero(t, id)
- // It seems the server doesn't populate most of the response
- // fields, but we just need the ID anyway.
-}
-
-func TestGetInteriorValidation(t *testing.T) {
- c := newClient(t)
-
- // Start validation job
- id, err := c.ValidateInteriorBasic(interiorUrl)
- require.NoError(t, err)
-
- // Poll until done
- timeout := 15 * time.Second
- period := time.Second
- ctx, cancel := context.WithTimeout(context.Background(), timeout)
- defer cancel()
- timer := time.NewTimer(period)
- for {
- select {
- case <-timer.C:
- rec, err := c.GetInteriorValidation(id)
- require.NoError(t, err)
- if rec.Status.IsFinal() {
- require.Equal(t, StatusValidated, rec.Status)
-
- require.Equal(t, id, rec.Id)
- require.Equal(t, interiorUrl, rec.SrcUrl)
- require.Equal(t, uint(210), rec.NPages)
- require.Empty(t, rec.Errors)
- require.NotEmpty(t, rec.ValidPkgIds)
- return
- }
- timer.Reset(period)
- case <-ctx.Done():
- t.Errorf("status still not finalized after %v", timeout)
- return
- }
- }
-}
-
-func TestUnmarshalCoverDimensions(t *testing.T) {
- t.Parallel()
- requireUnmarshalJsonEq(t,
- CoverDimensions{123.4, 567.8, Points},
- `{"width": "123.400", "height": "567.800", "unit": "pt"}`)
- requireUnmarshalJsonEq(t,
- CoverDimensions{123.4, 567.8, Millimeters},
- `{"width": "123.400", "height": "567.800", "unit": "mm"}`)
- requireUnmarshalJsonEq(t,
- CoverDimensions{123.4, 567.8, Inches},
- `{"width": "123.400", "height": "567.800", "unit": "inch"}`)
-}
-
-func TestMarshalCoverDimensionsReq(t *testing.T) {
- t.Parallel()
- requireMarshalJsonEq(t, `{
- "pod_package_id": "0600X0900.BW.STD.PB.060UW444.MXX",
- "interior_page_count": 210,
- "unit": "pt"}`,
- coverDimensionsReq{
- PkgId{
- UsTrade,
- Mono,
- Standard,
- Perfect,
- P60UncoatedWhite,
- Matte,
- NoLinen,
- NoFoil},
- 210,
- Points})
-}
-
-func TestCoverDimensions(t *testing.T) {
- c := newClient(t)
- mfg := PkgId{
- UsTrade,
- Mono,
- Standard,
- Perfect,
- P60UncoatedWhite,
- Matte,
- NoLinen,
- NoFoil,
- }
- dims, err := c.CoverDimensions(mfg, 210, Points)
- require.NoError(t, err)
- require.Equal(t, CoverDimensions{920, 666, Points}, dims)
-}
-
func newClient(t *testing.T) *Client {
t.Helper()
c, err := NewClient(t.Context(), clientKey, clientSecret)