Files
descrybe/apps/api/internal/woocommerce/sync_batch_test.go
T

135 lines
3.9 KiB
Go
Raw Normal View History

package woocommerce
import (
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"strings"
"sync/atomic"
"testing"
"time"
"github.com/google/uuid"
)
func TestListProductsBySKUsOneRequest(t *testing.T) {
var calls atomic.Int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/wp-json/wc/v3/products" {
t.Fatalf("path %s", r.URL.Path)
}
calls.Add(1)
sku := r.URL.Query().Get("sku")
if !strings.Contains(sku, "A1") || !strings.Contains(sku, "B2") {
t.Fatalf("sku query %q", sku)
}
_, _ = io.WriteString(w, `[{"id":11,"sku":"A1","name":"A"},{"id":22,"sku":"B2","name":"B"}]`)
}))
defer srv.Close()
c := NewClient(srv.URL, "ck", "cs", srv.Client())
found, err := c.ListProductsBySKUs(t.Context(), []string{"A1", "B2", "MISSING"})
if err != nil {
t.Fatal(err)
}
if calls.Load() != 1 {
t.Fatalf("calls=%d", calls.Load())
}
if found["A1"].ID != 11 || found["B2"].ID != 22 {
t.Fatalf("%+v", found)
}
if _, ok := found["MISSING"]; ok {
t.Fatal("unexpected missing hit")
}
}
func TestPushProductsBatchesSKULookup(t *testing.T) {
var skuCalls, batchCalls atomic.Int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == http.MethodGet && r.URL.Path == "/wp-json/wc/v3/products":
skuCalls.Add(1)
_, _ = io.WriteString(w, `[{"id":99,"sku":"EXISTING","name":"Exist"}]`)
case r.Method == http.MethodPost && r.URL.Path == "/wp-json/wc/v3/products/batch":
batchCalls.Add(1)
var req BatchRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
t.Fatal(err)
}
if len(req.Create) == 1 && req.Create[0].SKU == "NEW" {
_, _ = io.WriteString(w, `{"create":[{"id":100,"sku":"NEW"}],"update":[]}`)
return
}
if len(req.Update) == 1 && req.Update[0].SKU == "EXISTING" {
_, _ = io.WriteString(w, `{"create":[],"update":[{"id":99,"sku":"EXISTING"}]}`)
return
}
t.Fatalf("unexpected batch %+v", req)
default:
t.Fatalf("unexpected %s %s", r.Method, r.URL.Path)
}
}))
defer srv.Close()
c := NewClient(srv.URL, "ck", "cs", srv.Client())
svc := &Service{}
idExisting := uuid.MustParse("11111111-1111-1111-1111-111111111111")
idNew := uuid.MustParse("22222222-2222-2222-2222-222222222222")
pidExisting := "EXISTING"
pidNew := "NEW"
name := "Product"
opt := SyncOptions{
ProductIDs: map[string]int{},
MatchStrategy: "sku",
BatchSize: 25,
}
rows := []syncProductRow{
{ID: idExisting, ProductID: &pidExisting, Name: &name, MappedData: []byte(`{"sku":"EXISTING","price":"1"}`)},
{ID: idNew, ProductID: &pidNew, Name: &name, MappedData: []byte(`{"sku":"NEW","price":"2"}`)},
}
summary, err := svc.pushProducts(t.Context(), c, uuid.Nil, &opt, rows)
if err != nil {
t.Fatal(err)
}
if skuCalls.Load() != 1 {
t.Fatalf("expected 1 SKU lookup, got %d", skuCalls.Load())
}
if batchCalls.Load() != 2 {
t.Fatalf("expected create+update batches, got %d", batchCalls.Load())
}
if summary.Created != 1 || summary.Updated != 1 || summary.Failed != 0 {
t.Fatalf("summary=%+v", summary)
}
if opt.ProductIDs[idExisting.String()] != 99 || opt.ProductIDs[idNew.String()] != 100 {
t.Fatalf("product ids=%v", opt.ProductIDs)
}
}
func TestWooCommerceRetries429(t *testing.T) {
var calls atomic.Int32
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
n := calls.Add(1)
if n == 1 {
w.Header().Set("Retry-After", "0")
w.WriteHeader(http.StatusTooManyRequests)
_, _ = io.WriteString(w, `{"code":"woocommerce_rest_cannot_view"}`)
return
}
_, _ = io.WriteString(w, `[]`)
}))
defer srv.Close()
c := NewClient(srv.URL, "ck", "cs", srv.Client())
start := time.Now()
if err := c.TestConnection(t.Context()); err != nil {
t.Fatal(err)
}
if calls.Load() != 2 {
t.Fatalf("calls=%d", calls.Load())
}
if time.Since(start) > 3*time.Second {
t.Fatal("retry waited too long")
}
}