package lulutest import ( "fmt" "testing" "testing/synctest" "time" "github.com/shopspring/decimal" "github.com/stretchr/testify/require" "git.samanthony.xyz/lulu" ) const ( interiorUrl = "https://www.dropbox.com/sh/p3zh22vzsaegiri/AACOUn3LFKsITDzylh13bQpsa/161025/thesis2.pdf?dl=1" coverUrl = "https://www.dropbox.com/sh/p3zh22vzsaegiri/AADP367j0bTWlt8fCu-_tm2ia/161025/139056_cover.pdf?dl=1" ) func TestStartAndGetInteriorValidation(t *testing.T) { c := NewMockClient() defer c.Close() id, err := c.StartInteriorValidation(interiorUrl, DummyPkgId) require.NoError(t, err) val, err := c.GetInteriorValidation(id) require.NoError(t, err) require.Equal(t, id, val.Id) require.Equal(t, interiorUrl, val.SrcUrl) require.Equal(t, lulu.InteriorStatusNormalized, val.Status) } func TestStartInteriorValidationBasic(t *testing.T) { c := NewMockClient() defer c.Close() id, err := c.StartInteriorValidationBasic(interiorUrl) require.NoError(t, err) val, err := c.GetInteriorValidation(id) require.NoError(t, err) require.Equal(t, id, val.Id) require.Equal(t, interiorUrl, val.SrcUrl) } func TestGetInteriorValidationNotFound(t *testing.T) { c := NewMockClient() defer c.Close() _, err := c.GetInteriorValidation(0) require.Error(t, err) } func TestCoverDimensions(t *testing.T) { c := NewMockClient() defer c.Close() dims, err := c.CoverDimensions(DummyPkgId, 210, lulu.Points) require.NoError(t, err) require.Equal(t, lulu.Points, dims.Unit) require.NotZero(t, dims.Width) require.NotZero(t, dims.Height) } func TestStartAndGetCoverValidation(t *testing.T) { c := NewMockClient() defer c.Close() id, err := c.StartCoverValidation(coverUrl, DummyPkgId, 210) require.NoError(t, err) val, err := c.GetCoverValidation(id) require.NoError(t, err) require.Equal(t, id, val.Id) require.Equal(t, coverUrl, val.SrcUrl) require.Equal(t, uint(210), val.NPages) require.Equal(t, lulu.CoverStatusNormalized, val.Status) } func TestGetCoverValidationNotFound(t *testing.T) { c := NewMockClient() defer c.Close() _, err := c.GetCoverValidation(0) require.Error(t, err) } func TestCost(t *testing.T) { c := NewMockClient() defer c.Close() items := []lulu.CostLineItem{ {Mfg: DummyPkgId, Quantity: 2}, {Mfg: DummyPkgId, Quantity: 1}, } addr := DummyShipAddr addr.Street1 = "1 Main St" cost, val, err := c.Cost(items, addr, lulu.Mail) require.NoError(t, err) require.Equal(t, "USD", cost.Currency) require.Len(t, cost.LineItemCosts, len(items)) for i, it := range cost.LineItemCosts { require.Equal(t, items[i].Quantity, it.Quantity) require.True(t, it.TotalCostInclTax.GreaterThan(decimal.Zero)) } require.True(t, cost.TotalCostInclTax.GreaterThan(cost.TotalCostExclTax)) require.Equal(t, addr, val.Address) require.Equal(t, "1 Main rd", val.Suggested.Street1) } func TestPrint(t *testing.T) { c := NewMockClient() defer c.Close() items := MakePrintables(c, 2) j, err := c.Print(DummyEmailAddr, "ext-1", 5*time.Minute, DummyShipAddr, lulu.Mail, items) require.NoError(t, err) require.Zero(t, j.Id) require.Equal(t, "ext-1", j.ExternalId) require.Equal(t, DummyEmailAddr, j.Contact) require.Equal(t, lulu.OrderProductionDelayed, j.Status.Status) require.Len(t, j.Items, len(items)) seen := make(map[lulu.PrintableId]bool) for i, it := range j.Items { require.Equal(t, items[i].ExternalId, it.ExternalId) require.Equal(t, items[i].Mfg, it.Mfg) require.Equal(t, items[i].Quantity, it.Quantity) require.NotEmpty(t, it.PrintableId) require.False(t, seen[it.PrintableId], "duplicate printable id %q", it.PrintableId) seen[it.PrintableId] = true } // A second job should get the next sequential id. j2, err := c.Print(DummyEmailAddr, "ext-2", 5*time.Minute, DummyShipAddr, lulu.Mail, items) require.NoError(t, err) require.Equal(t, j.Id+1, j2.Id) } func TestReprint(t *testing.T) { c := NewMockClient() defer c.Close() items := MakePrintables(c, 2) j, err := c.Print(DummyEmailAddr, "orig", 5*time.Minute, DummyShipAddr, lulu.Mail, items) require.NoError(t, err) rpbs := make([]lulu.Reprintable, len(j.Items)) for i, it := range j.Items { rpbs[i] = lulu.Reprintable{ ExternalId: it.ExternalId, PrintableId: it.PrintableId, Quantity: it.Quantity, Title: it.Title, } } rj, err := c.Reprint(DummyEmailAddr, "reprint", 5*time.Minute, DummyShipAddr, lulu.Mail, rpbs) require.NoError(t, err) require.Equal(t, j.Id+1, rj.Id) require.Len(t, rj.Items, len(rpbs)) for i, it := range rj.Items { require.Equal(t, rpbs[i].PrintableId, it.PrintableId) require.Equal(t, items[i].Mfg, it.Mfg) } } func TestMakeReprintables(t *testing.T) { c := NewMockClient() defer c.Close() rpbs, err := MakeReprintables(c, 2) require.NoError(t, err) require.Len(t, rpbs, 2) for _, r := range rpbs { require.NotEmpty(t, r.PrintableId) require.NotZero(t, r.Quantity) } j, err := c.Reprint(DummyEmailAddr, "eid", 5*time.Minute, DummyShipAddr, lulu.Mail, rpbs) require.NoError(t, err) require.Len(t, j.Items, 2) } func TestReprintUnknownPrintable(t *testing.T) { c := NewMockClient() defer c.Close() rpbs := []lulu.Reprintable{{ ExternalId: "ext", PrintableId: lulu.PrintableId("does-not-exist"), Quantity: 1, Title: "Ghost", }} _, err := c.Reprint(DummyEmailAddr, "eid", 5*time.Minute, DummyShipAddr, lulu.Mail, rpbs) require.Error(t, err) } func TestJob(t *testing.T) { c := NewMockClient() defer c.Close() items := MakePrintables(c, 1) j, err := c.Print(DummyEmailAddr, "eid", 5*time.Minute, DummyShipAddr, lulu.Mail, items) require.NoError(t, err) got, err := c.Job(j.Id) require.NoError(t, err) require.Equal(t, j.Id, got.Id) require.Equal(t, j.ExternalId, got.ExternalId) } func TestJobNotFound(t *testing.T) { c := NewMockClient() defer c.Close() _, err := c.Job(0) require.Error(t, err) } func TestJobs(t *testing.T) { c := NewMockClient() defer c.Close() items := MakePrintables(c, 1) want := make(map[uint64]string) for i := range 3 { eid := fmt.Sprintf("eid-%d", i) j, err := c.Print(DummyEmailAddr, eid, 5*time.Minute, DummyShipAddr, lulu.Mail, items) require.NoError(t, err) want[j.Id] = eid } js, err := c.Jobs() require.NoError(t, err) require.Len(t, js, len(want)) for _, j := range js { require.Equal(t, want[j.Id], j.ExternalId) } } func TestJobsEmpty(t *testing.T) { c := NewMockClient() defer c.Close() js, err := c.Jobs() require.NoError(t, err) require.Empty(t, js) } func TestCancelWhileDelayed(t *testing.T) { c := NewMockClient() defer c.Close() items := MakePrintables(c, 1) j, err := c.Print(DummyEmailAddr, "eid", 5*time.Minute, DummyShipAddr, lulu.Mail, items) require.NoError(t, err) require.NoError(t, c.Cancel(j.Id)) got, err := c.Job(j.Id) require.NoError(t, err) require.Equal(t, lulu.OrderCanceled, got.Status.Status) } func TestCancelAfterProduction(t *testing.T) { synctest.Test(t, func(t *testing.T) { c := NewMockClient() defer c.Close() items := MakePrintables(c, 1) delay := 10 * time.Minute j, err := c.Print(DummyEmailAddr, "eid", delay, DummyShipAddr, lulu.Mail, items) require.NoError(t, err) time.Sleep(delay + time.Millisecond) // let the prod timer fire got, err := c.Job(j.Id) require.NoError(t, err) require.Equal(t, lulu.OrderInProduction, got.Status.Status) err = c.Cancel(j.Id) require.Error(t, err) got, err = c.Job(j.Id) require.NoError(t, err) require.Equal(t, lulu.OrderInProduction, got.Status.Status) }) } func TestCancelNotFound(t *testing.T) { c := NewMockClient() defer c.Close() require.Error(t, c.Cancel(0)) } func TestJobLifecycle(t *testing.T) { synctest.Test(t, func(t *testing.T) { c := NewMockClient() defer c.Close() items := MakePrintables(c, 1) delay := 10 * time.Minute j, err := c.Print(DummyEmailAddr, "eid", delay, DummyShipAddr, lulu.Mail, items) require.NoError(t, err) require.Equal(t, lulu.OrderProductionDelayed, j.Status.Status) time.Sleep(delay + time.Millisecond) // let the prod timer fire got, err := c.Job(j.Id) require.NoError(t, err) require.Equal(t, lulu.OrderInProduction, got.Status.Status) time.Sleep(shipDelay) // let the ship timer fire got, err = c.Job(j.Id) require.NoError(t, err) require.Equal(t, lulu.OrderShipped, got.Status.Status) time.Sleep(deliverDelay) // let the arrive timer fire got, err = c.Job(j.Id) require.NoError(t, err) require.Equal(t, lulu.OrderDelivered, got.Status.Status) }) }