cart and checkout
Build and Publish / BuildAndDeployAmd64 (push) Failing after 4s
Build and Publish / BuildAndDeployArm64 (push) Failing after 6s

This commit is contained in:
2026-06-27 19:49:00 +02:00
parent 492f54ff45
commit 528c59bfd3
67 changed files with 3618 additions and 1031 deletions
+87 -10
View File
@@ -6,6 +6,8 @@ import (
"fmt"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"time"
@@ -105,6 +107,12 @@ func (a *testProfileApplier) Apply(ctx context.Context, id uint64, msgs ...proto
g.Checkouts = append(g.Checkouts, profile.LinkedCheckout{CheckoutId: m.CheckoutId, CartId: m.CartId})
case *messages.LinkOrder:
g.Orders = append(g.Orders, profile.LinkedOrder{OrderReference: m.OrderReference, CartId: m.CartId, Status: m.Status})
case *messages.AnonymizeProfile:
g.Name = ""
g.Email = ""
g.Phone = ""
g.AvatarUrl = ""
g.Addresses = nil
}
}
return &actor.MutationResult[profile.ProfileGrain]{
@@ -138,7 +146,7 @@ func testProfileID(t *testing.T, applier *testProfileApplier) string {
func TestGetCustomer(t *testing.T) {
applier := newTestProfileApplier()
id := testProfileID(t, applier)
handler := CustomerHandler(applier)
handler := CustomerHandler(applier, "")
// Set up some profile data
pid, _ := profile.ParseProfileId(id)
@@ -173,7 +181,7 @@ func TestGetCustomer(t *testing.T) {
func TestGetCustomerNotFound(t *testing.T) {
applier := newTestProfileApplier()
handler := CustomerHandler(applier)
handler := CustomerHandler(applier, "")
// "nonexistent" is actually valid base62, so use an ID with characters outside the alphabet.
req := httptest.NewRequest("GET", "/!invalid!", nil)
@@ -188,7 +196,7 @@ func TestGetCustomerNotFound(t *testing.T) {
func TestUpdateCustomer(t *testing.T) {
applier := newTestProfileApplier()
id := testProfileID(t, applier)
handler := CustomerHandler(applier)
handler := CustomerHandler(applier, "")
body := `{"name": "Bob", "email": "bob@example.com", "phone": "+46701234567", "language": "sv", "currency": "SEK"}`
req := httptest.NewRequest("PUT", fmt.Sprintf("/%s", id), strings.NewReader(body))
@@ -224,7 +232,7 @@ func TestUpdateCustomer(t *testing.T) {
func TestAddAddress(t *testing.T) {
applier := newTestProfileApplier()
id := testProfileID(t, applier)
handler := CustomerHandler(applier)
handler := CustomerHandler(applier, "")
body := `{
"label": "Home",
@@ -266,7 +274,7 @@ func TestAddAddress(t *testing.T) {
func TestAddAddressMissingRequired(t *testing.T) {
applier := newTestProfileApplier()
id := testProfileID(t, applier)
handler := CustomerHandler(applier)
handler := CustomerHandler(applier, "")
// Missing addressLine1
body := `{"city": "Stockholm", "zip": "111 22", "country": "SE"}`
@@ -283,7 +291,7 @@ func TestAddAddressMissingRequired(t *testing.T) {
func TestUpdateAddress(t *testing.T) {
applier := newTestProfileApplier()
id := testProfileID(t, applier)
handler := CustomerHandler(applier)
handler := CustomerHandler(applier, "")
// First add an address
pid, _ := profile.ParseProfileId(id)
@@ -337,7 +345,7 @@ func TestUpdateAddress(t *testing.T) {
func TestUpdateAddressInvalidID(t *testing.T) {
applier := newTestProfileApplier()
id := testProfileID(t, applier)
handler := CustomerHandler(applier)
handler := CustomerHandler(applier, "")
body := `{"label": "New Home"}`
req := httptest.NewRequest("PUT", fmt.Sprintf("/%s/addresses/abc", id), strings.NewReader(body))
@@ -353,7 +361,7 @@ func TestUpdateAddressInvalidID(t *testing.T) {
func TestRemoveAddress(t *testing.T) {
applier := newTestProfileApplier()
id := testProfileID(t, applier)
handler := CustomerHandler(applier)
handler := CustomerHandler(applier, "")
// First add an address
pid, _ := profile.ParseProfileId(id)
@@ -398,7 +406,7 @@ func TestRemoveAddressNotFound(t *testing.T) {
applier.Get(context.Background(), uint64(pid))
id := pid.String()
handler := CustomerHandler(applier)
handler := CustomerHandler(applier, "")
req := httptest.NewRequest("DELETE", fmt.Sprintf("/%s/addresses/999", id), nil)
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
@@ -444,7 +452,7 @@ func TestRemoveAddressNotFoundMutation(t *testing.T) {
func TestCustomerHandlerInvalidID(t *testing.T) {
applier := newTestProfileApplier()
handler := CustomerHandler(applier)
handler := CustomerHandler(applier, "")
// Path "/" now has POST / registered (create customer), so GET / is 405.
// Paths with invalid base62 characters should get 400.
@@ -496,3 +504,72 @@ func TestCustomerHandlerThroughCombinedMount(t *testing.T) {
t.Fatalf("expected id %q, got %q", id, resp.Id)
}
}
type testCredentialDeleter struct {
deletedEmail string
}
func (d *testCredentialDeleter) Delete(_ context.Context, email string) (bool, error) {
d.deletedEmail = email
return true, nil
}
func TestDeleteCustomer(t *testing.T) {
applier := newTestProfileApplier()
id := testProfileID(t, applier)
deleter := &testCredentialDeleter{}
auditPath := filepath.Join(t.TempDir(), "audit.log")
handler := CustomerHandler(applier, auditPath, deleter)
// Set up some profile data
pid, _ := profile.ParseProfileId(id)
applier.Apply(context.Background(), uint64(pid), &messages.SetProfile{
Name: proto.String("Alice"),
Email: proto.String("alice@example.com"),
})
applier.Apply(context.Background(), uint64(pid), &messages.AddAddress{
Address: &messages.Address{
Label: "Home",
AddressLine1: "Storgatan 1",
City: "Stockholm",
Zip: "111 22",
Country: "SE",
},
})
// DELETE /customers/{id}
req := httptest.NewRequest("DELETE", fmt.Sprintf("/%s", id), nil)
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
if rec.Code != http.StatusNoContent {
t.Fatalf("expected 204 No Content, got %d. Body: %s", rec.Code, rec.Body.String())
}
// Verify credentials deleted
if deleter.deletedEmail != "alice@example.com" {
t.Fatalf("expected deleted email 'alice@example.com', got %q", deleter.deletedEmail)
}
// Verify profile is anonymized
g, _ := applier.Get(context.Background(), uint64(pid))
if g.Name != "" || g.Email != "" || g.Addresses != nil {
t.Fatalf("expected profile to be anonymized, got Name=%q, Email=%q, Addresses=%v", g.Name, g.Email, g.Addresses)
}
// Verify audit log has the correct entry and no PII
logBytes, err := os.ReadFile(auditPath)
if err != nil {
t.Fatalf("failed to read audit log: %v", err)
}
logContent := string(logBytes)
if !strings.Contains(logContent, "ACTION=GDPR_ERASURE") {
t.Fatal("expected audit log to record erasure action")
}
if !strings.Contains(logContent, "PROFILE_ID="+id) {
t.Fatal("expected audit log to record profile ID")
}
if strings.Contains(logContent, "Alice") || strings.Contains(logContent, "alice@example.com") {
t.Fatal("expected audit log to exclude PII")
}
}