@payloadcms/plugin-ecommerce 3.91.0-internal.c1569dc → 4.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/LICENSE.md +1 -1
  2. package/dist/collections/addresses/createAddressesCollection.d.ts.map +1 -1
  3. package/dist/collections/addresses/createAddressesCollection.js +1 -0
  4. package/dist/collections/addresses/createAddressesCollection.js.map +1 -1
  5. package/dist/collections/addresses/hooks/beforeChange.d.ts.map +1 -1
  6. package/dist/collections/addresses/hooks/beforeChange.js +3 -2
  7. package/dist/collections/addresses/hooks/beforeChange.js.map +1 -1
  8. package/dist/collections/carts/beforeChange.d.ts.map +1 -1
  9. package/dist/collections/carts/beforeChange.js +2 -0
  10. package/dist/collections/carts/beforeChange.js.map +1 -1
  11. package/dist/collections/carts/createCartsCollection.d.ts.map +1 -1
  12. package/dist/collections/carts/createCartsCollection.js +1 -0
  13. package/dist/collections/carts/createCartsCollection.js.map +1 -1
  14. package/dist/collections/orders/createOrdersCollection.d.ts.map +1 -1
  15. package/dist/collections/orders/createOrdersCollection.js +1 -0
  16. package/dist/collections/orders/createOrdersCollection.js.map +1 -1
  17. package/dist/collections/products/createProductsCollection.d.ts.map +1 -1
  18. package/dist/collections/products/createProductsCollection.js +1 -0
  19. package/dist/collections/products/createProductsCollection.js.map +1 -1
  20. package/dist/collections/transactions/createTransactionsCollection.d.ts.map +1 -1
  21. package/dist/collections/transactions/createTransactionsCollection.js +1 -0
  22. package/dist/collections/transactions/createTransactionsCollection.js.map +1 -1
  23. package/dist/collections/variants/createVariantOptionsCollection.d.ts.map +1 -1
  24. package/dist/collections/variants/createVariantOptionsCollection.js +1 -0
  25. package/dist/collections/variants/createVariantOptionsCollection.js.map +1 -1
  26. package/dist/collections/variants/createVariantTypesCollection.d.ts.map +1 -1
  27. package/dist/collections/variants/createVariantTypesCollection.js +1 -0
  28. package/dist/collections/variants/createVariantTypesCollection.js.map +1 -1
  29. package/dist/collections/variants/createVariantsCollection/hooks/beforeChange.d.ts.map +1 -1
  30. package/dist/collections/variants/createVariantsCollection/hooks/beforeChange.js +2 -0
  31. package/dist/collections/variants/createVariantsCollection/hooks/beforeChange.js.map +1 -1
  32. package/dist/collections/variants/createVariantsCollection/hooks/validateOptions.d.ts.map +1 -1
  33. package/dist/collections/variants/createVariantsCollection/hooks/validateOptions.js +1 -0
  34. package/dist/collections/variants/createVariantsCollection/hooks/validateOptions.js.map +1 -1
  35. package/dist/collections/variants/createVariantsCollection/index.d.ts.map +1 -1
  36. package/dist/collections/variants/createVariantsCollection/index.js +1 -0
  37. package/dist/collections/variants/createVariantsCollection/index.js.map +1 -1
  38. package/dist/endpoints/confirmOrder.d.ts.map +1 -1
  39. package/dist/endpoints/confirmOrder.js +7 -0
  40. package/dist/endpoints/confirmOrder.js.map +1 -1
  41. package/dist/endpoints/initiatePayment.d.ts.map +1 -1
  42. package/dist/endpoints/initiatePayment.js +2 -0
  43. package/dist/endpoints/initiatePayment.js.map +1 -1
  44. package/dist/exports/types.d.ts +1 -1
  45. package/dist/exports/types.d.ts.map +1 -1
  46. package/dist/exports/types.js.map +1 -1
  47. package/dist/fields/pricesField.d.ts.map +1 -1
  48. package/dist/fields/pricesField.js +39 -39
  49. package/dist/fields/pricesField.js.map +1 -1
  50. package/dist/fields/variantsFields.js +3 -1
  51. package/dist/fields/variantsFields.js.map +1 -1
  52. package/dist/index.d.ts +1 -2
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +24 -24
  55. package/dist/index.js.map +1 -1
  56. package/dist/payments/adapters/stripe/confirmOrder.js +1 -0
  57. package/dist/payments/adapters/stripe/confirmOrder.js.map +1 -1
  58. package/dist/payments/adapters/stripe/initiatePayment.d.ts.map +1 -1
  59. package/dist/payments/adapters/stripe/initiatePayment.js +1 -0
  60. package/dist/payments/adapters/stripe/initiatePayment.js.map +1 -1
  61. package/dist/react/provider/index.d.ts.map +1 -1
  62. package/dist/react/provider/index.js.map +1 -1
  63. package/dist/translations/languages/ar.d.ts.map +1 -1
  64. package/dist/translations/languages/az.d.ts.map +1 -1
  65. package/dist/translations/languages/bg.d.ts.map +1 -1
  66. package/dist/translations/languages/ca.d.ts.map +1 -1
  67. package/dist/translations/languages/cs.d.ts.map +1 -1
  68. package/dist/translations/languages/da.d.ts.map +1 -1
  69. package/dist/translations/languages/de.d.ts.map +1 -1
  70. package/dist/translations/languages/en.d.ts.map +1 -1
  71. package/dist/translations/languages/es.d.ts.map +1 -1
  72. package/dist/translations/languages/et.d.ts.map +1 -1
  73. package/dist/translations/languages/fa.d.ts.map +1 -1
  74. package/dist/translations/languages/fr.d.ts.map +1 -1
  75. package/dist/translations/languages/he.d.ts.map +1 -1
  76. package/dist/translations/languages/hr.d.ts.map +1 -1
  77. package/dist/translations/languages/hu.d.ts.map +1 -1
  78. package/dist/translations/languages/hy.d.ts.map +1 -1
  79. package/dist/translations/languages/is.d.ts.map +1 -1
  80. package/dist/translations/languages/it.d.ts.map +1 -1
  81. package/dist/translations/languages/ja.d.ts.map +1 -1
  82. package/dist/translations/languages/ko.d.ts.map +1 -1
  83. package/dist/translations/languages/lt.d.ts.map +1 -1
  84. package/dist/translations/languages/my.d.ts.map +1 -1
  85. package/dist/translations/languages/nb.d.ts.map +1 -1
  86. package/dist/translations/languages/nl.d.ts.map +1 -1
  87. package/dist/translations/languages/pl.d.ts.map +1 -1
  88. package/dist/translations/languages/pt.d.ts.map +1 -1
  89. package/dist/translations/languages/ro.d.ts.map +1 -1
  90. package/dist/translations/languages/rs.d.ts.map +1 -1
  91. package/dist/translations/languages/rsLatin.d.ts.map +1 -1
  92. package/dist/translations/languages/ru.d.ts.map +1 -1
  93. package/dist/translations/languages/sk.d.ts.map +1 -1
  94. package/dist/translations/languages/sl.d.ts.map +1 -1
  95. package/dist/translations/languages/sv.d.ts.map +1 -1
  96. package/dist/translations/languages/ta.d.ts.map +1 -1
  97. package/dist/translations/languages/th.d.ts.map +1 -1
  98. package/dist/translations/languages/tr.d.ts.map +1 -1
  99. package/dist/translations/languages/uk.d.ts.map +1 -1
  100. package/dist/translations/languages/vi.d.ts.map +1 -1
  101. package/dist/translations/languages/zh.d.ts.map +1 -1
  102. package/dist/translations/languages/zhTw.d.ts.map +1 -1
  103. package/dist/types/index.d.ts +9 -2
  104. package/dist/types/index.d.ts.map +1 -1
  105. package/dist/types/index.js.map +1 -1
  106. package/dist/ui/PriceInput/FormattedInput.js +2 -2
  107. package/dist/ui/PriceInput/FormattedInput.js.map +1 -1
  108. package/dist/ui/PriceInput/index.css +19 -31
  109. package/dist/ui/PriceInput/index.d.ts.map +1 -1
  110. package/dist/ui/PriceInput/index.js.map +1 -1
  111. package/dist/ui/PriceRowLabel/index.css +2 -2
  112. package/dist/ui/VariantOptionsSelector/index.css +8 -10
  113. package/dist/ui/VariantOptionsSelector/index.d.ts.map +1 -1
  114. package/dist/ui/VariantOptionsSelector/index.js +3 -1
  115. package/dist/ui/VariantOptionsSelector/index.js.map +1 -1
  116. package/dist/utilities/pushTypeScriptProperties.js +1 -1
  117. package/dist/utilities/pushTypeScriptProperties.js.map +1 -1
  118. package/package.json +10 -10
  119. package/dist/collections/carts/operations/defaultCartItemMatcher.spec.js +0 -358
  120. package/dist/collections/carts/operations/defaultCartItemMatcher.spec.js.map +0 -1
  121. package/dist/collections/orders/createOrdersCollection.spec.js +0 -20
  122. package/dist/collections/orders/createOrdersCollection.spec.js.map +0 -1
  123. package/dist/endpoints/confirmOrder.spec.js +0 -509
  124. package/dist/endpoints/confirmOrder.spec.js.map +0 -1
  125. package/dist/fields/statusField.spec.js +0 -9
  126. package/dist/fields/statusField.spec.js.map +0 -1
  127. package/dist/payments/adapters/stripe/confirmOrder.spec.js +0 -255
  128. package/dist/payments/adapters/stripe/confirmOrder.spec.js.map +0 -1
  129. package/dist/payments/adapters/stripe/validateSettlement.spec.js +0 -434
  130. package/dist/payments/adapters/stripe/validateSettlement.spec.js.map +0 -1
  131. package/dist/utilities/accessComposition.spec.js +0 -765
  132. package/dist/utilities/accessComposition.spec.js.map +0 -1
  133. package/dist/utilities/defaultProductsValidation.spec.js +0 -384
  134. package/dist/utilities/defaultProductsValidation.spec.js.map +0 -1
  135. package/dist/utilities/getCollectionSlugMap.spec.js +0 -254
  136. package/dist/utilities/getCollectionSlugMap.spec.js.map +0 -1
  137. package/dist/utilities/sanitizePluginConfig.spec.js +0 -516
  138. package/dist/utilities/sanitizePluginConfig.spec.js.map +0 -1
@@ -1,434 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { getRelationshipID, normalizeCartItems, normalizeEmail, validateSettlement } from './validateSettlement.js';
3
- const createTransaction = (overrides = {})=>({
4
- amount: 1000,
5
- cart: 'cart-123',
6
- currency: 'USD',
7
- customer: 'user-123',
8
- id: 'txn-123',
9
- items: [
10
- {
11
- id: 'item-1',
12
- product: 'product-123',
13
- quantity: 1
14
- }
15
- ],
16
- status: 'pending',
17
- stripe: {
18
- customerID: 'cus-123',
19
- paymentIntentID: 'pi_123'
20
- },
21
- ...overrides
22
- });
23
- const createPaymentIntent = (overrides = {})=>({
24
- amount: 1000,
25
- currency: 'usd',
26
- customer: 'cus-123',
27
- id: 'pi_123',
28
- metadata: {
29
- cartID: 'cart-123'
30
- },
31
- status: 'succeeded',
32
- ...overrides
33
- });
34
- const createAuthenticatedValidation = (overrides = {})=>({
35
- canonicalCartID: 'cart-123',
36
- cartItemsSnapshot: [
37
- {
38
- id: 'item-1',
39
- product: 'product-123',
40
- quantity: 1
41
- }
42
- ],
43
- customerEmail: 'buyer@example.com',
44
- paymentIntent: createPaymentIntent(),
45
- paymentIntentID: 'pi_123',
46
- transaction: createTransaction(),
47
- user: {
48
- id: 'user-123'
49
- },
50
- ...overrides
51
- });
52
- describe('Stripe settlement normalization', ()=>{
53
- it('should extract relationship IDs as strings', ()=>{
54
- expect(getRelationshipID({
55
- id: 123
56
- })).toBe('123');
57
- expect(getRelationshipID(123)).toBe('123');
58
- expect(getRelationshipID('123')).toBe('123');
59
- });
60
- it('should reject empty or malformed relationship IDs', ()=>{
61
- expect(getRelationshipID('')).toBeUndefined();
62
- expect(getRelationshipID({
63
- id: ''
64
- })).toBeUndefined();
65
- expect(getRelationshipID({
66
- id: {
67
- id: 'nested-id'
68
- }
69
- })).toBeUndefined();
70
- });
71
- it('should normalize email case and outer whitespace', ()=>{
72
- expect(normalizeEmail(' Buyer@Example.COM ')).toBe('buyer@example.com');
73
- });
74
- it('should normalize only root relationships while preserving nested custom data', ()=>{
75
- expect(normalizeCartItems([
76
- {
77
- custom: {
78
- gift: true
79
- },
80
- product: {
81
- id: 123
82
- },
83
- quantity: 2,
84
- selections: [
85
- {
86
- variant: {
87
- id: 'variant-456'
88
- }
89
- }
90
- ],
91
- variant: 456
92
- }
93
- ])).toEqual([
94
- {
95
- custom: {
96
- gift: true
97
- },
98
- product: '123',
99
- quantity: 2,
100
- selections: [
101
- {
102
- variant: {
103
- id: 'variant-456'
104
- }
105
- }
106
- ],
107
- variant: '456'
108
- }
109
- ]);
110
- });
111
- });
112
- describe('validateSettlement', ()=>{
113
- it('should accept a valid authenticated settlement that is pending and unlinked', ()=>{
114
- expect(()=>validateSettlement(createAuthenticatedValidation())).not.toThrow();
115
- });
116
- it('should accept a valid guest settlement with normalized emails', ()=>{
117
- const transaction = createTransaction({
118
- customer: undefined,
119
- customerEmail: ' Buyer@Example.com '
120
- });
121
- expect(()=>validateSettlement(createAuthenticatedValidation({
122
- customerEmail: 'buyer@example.COM',
123
- transaction,
124
- user: undefined
125
- }))).not.toThrow();
126
- });
127
- it.each([
128
- {
129
- label: 'missing',
130
- user: {}
131
- },
132
- {
133
- label: 'empty',
134
- user: {
135
- id: ''
136
- }
137
- },
138
- {
139
- label: 'malformed',
140
- user: {
141
- id: {}
142
- }
143
- }
144
- ])('should reject a $label ID on a present authenticated principal', ({ user })=>{
145
- const transaction = createTransaction({
146
- customer: undefined,
147
- customerEmail: 'buyer@example.com'
148
- });
149
- expect(()=>validateSettlement(createAuthenticatedValidation({
150
- transaction,
151
- user
152
- }))).toThrow('customer');
153
- });
154
- it('should reject a requested PaymentIntent that does not match the transaction', ()=>{
155
- expect(()=>validateSettlement(createAuthenticatedValidation({
156
- transaction: createTransaction({
157
- stripe: {
158
- customerID: 'cus-123',
159
- paymentIntentID: 'pi_other'
160
- }
161
- })
162
- }))).toThrow('PaymentIntent');
163
- });
164
- it('should reject a canonical cart that does not match the transaction cart', ()=>{
165
- expect(()=>validateSettlement(createAuthenticatedValidation({
166
- transaction: createTransaction({
167
- cart: 'cart-other'
168
- })
169
- }))).toThrow('cart');
170
- });
171
- it('should reject a canonical cart that does not match PaymentIntent metadata', ()=>{
172
- expect(()=>validateSettlement(createAuthenticatedValidation({
173
- paymentIntent: createPaymentIntent({
174
- metadata: {
175
- cartID: 'cart-other'
176
- }
177
- })
178
- }))).toThrow('cart');
179
- });
180
- it('should reject an authenticated customer that does not own the transaction', ()=>{
181
- expect(()=>validateSettlement(createAuthenticatedValidation({
182
- transaction: createTransaction({
183
- customer: 'user-other'
184
- })
185
- }))).toThrow('customer');
186
- });
187
- it('should reject a guest transaction that belongs to an authenticated customer', ()=>{
188
- expect(()=>validateSettlement(createAuthenticatedValidation({
189
- transaction: createTransaction({
190
- customerEmail: 'buyer@example.com'
191
- }),
192
- user: undefined
193
- }))).toThrow('customer');
194
- });
195
- it('should reject a guest transaction with a different email', ()=>{
196
- expect(()=>validateSettlement(createAuthenticatedValidation({
197
- transaction: createTransaction({
198
- customer: undefined,
199
- customerEmail: 'other@example.com'
200
- }),
201
- user: undefined
202
- }))).toThrow('email');
203
- });
204
- it('should reject a Stripe customer that does not match the transaction', ()=>{
205
- expect(()=>validateSettlement(createAuthenticatedValidation({
206
- paymentIntent: createPaymentIntent({
207
- customer: 'cus-other'
208
- })
209
- }))).toThrow('Stripe customer');
210
- });
211
- it('should reject a Stripe amount that does not match the transaction', ()=>{
212
- expect(()=>validateSettlement(createAuthenticatedValidation({
213
- paymentIntent: createPaymentIntent({
214
- amount: 999
215
- })
216
- }))).toThrow('amount');
217
- });
218
- it('should reject a Stripe currency that does not match after uppercasing', ()=>{
219
- expect(()=>validateSettlement(createAuthenticatedValidation({
220
- paymentIntent: createPaymentIntent({
221
- currency: 'eur'
222
- })
223
- }))).toThrow('currency');
224
- });
225
- it('should reject a lower-case stored transaction currency', ()=>{
226
- expect(()=>validateSettlement(createAuthenticatedValidation({
227
- transaction: createTransaction({
228
- currency: 'usd'
229
- })
230
- }))).toThrow('currency');
231
- });
232
- it('should accept relationship objects and scalar IDs as equivalent item data', ()=>{
233
- const transaction = createTransaction({
234
- items: [
235
- {
236
- id: 'item-1',
237
- product: {
238
- id: 123
239
- },
240
- quantity: 1,
241
- variant: {
242
- id: 456
243
- }
244
- }
245
- ]
246
- });
247
- expect(()=>validateSettlement(createAuthenticatedValidation({
248
- cartItemsSnapshot: [
249
- {
250
- id: 'item-1',
251
- product: '123',
252
- quantity: 1,
253
- variant: '456'
254
- }
255
- ],
256
- transaction
257
- }))).not.toThrow();
258
- });
259
- it('should reject an item quantity mismatch', ()=>{
260
- expect(()=>validateSettlement(createAuthenticatedValidation({
261
- cartItemsSnapshot: [
262
- {
263
- id: 'item-1',
264
- product: 'product-123',
265
- quantity: 2
266
- }
267
- ]
268
- }))).toThrow('items');
269
- });
270
- it('should reject an item custom-property mismatch', ()=>{
271
- expect(()=>validateSettlement(createAuthenticatedValidation({
272
- cartItemsSnapshot: [
273
- {
274
- giftMessage: 'surprise',
275
- id: 'item-1',
276
- product: 'product-123',
277
- quantity: 1
278
- }
279
- ]
280
- }))).toThrow('items');
281
- });
282
- it('should treat a persisted null root variant as equivalent to an omitted snapshot variant', ()=>{
283
- expect(()=>validateSettlement(createAuthenticatedValidation({
284
- transaction: createTransaction({
285
- items: [
286
- {
287
- id: 'item-1',
288
- product: 'product-123',
289
- quantity: 1,
290
- variant: null
291
- }
292
- ]
293
- })
294
- }))).not.toThrow();
295
- });
296
- it('should reject a null root product', ()=>{
297
- expect(()=>validateSettlement(createAuthenticatedValidation({
298
- cartItemsSnapshot: [
299
- {
300
- id: 'item-1',
301
- product: null,
302
- quantity: 1
303
- }
304
- ]
305
- }))).toThrow();
306
- });
307
- it.each([
308
- {
309
- label: 'malformed object',
310
- variant: {}
311
- },
312
- {
313
- label: 'blank scalar ID',
314
- variant: ''
315
- },
316
- {
317
- label: 'blank object ID',
318
- variant: {
319
- id: ''
320
- }
321
- },
322
- {
323
- label: 'nested object ID',
324
- variant: {
325
- id: {
326
- id: 'variant-123'
327
- }
328
- }
329
- }
330
- ])('should reject a $label for a non-null root variant', ({ variant })=>{
331
- expect(()=>validateSettlement(createAuthenticatedValidation({
332
- cartItemsSnapshot: [
333
- {
334
- id: 'item-1',
335
- product: 'product-123',
336
- quantity: 1,
337
- variant
338
- }
339
- ]
340
- }))).toThrow();
341
- });
342
- it('should reject equivalent empty scalar and object relationship IDs', ()=>{
343
- expect(()=>validateSettlement(createAuthenticatedValidation({
344
- cartItemsSnapshot: [
345
- {
346
- id: 'item-1',
347
- product: 'product-123',
348
- quantity: 1,
349
- variant: ''
350
- }
351
- ],
352
- transaction: createTransaction({
353
- items: [
354
- {
355
- id: 'item-1',
356
- product: 'product-123',
357
- quantity: 1,
358
- variant: {
359
- id: ''
360
- }
361
- }
362
- ]
363
- })
364
- }))).toThrow();
365
- });
366
- it('should preserve nested custom variant null when comparing against a missing nested key', ()=>{
367
- expect(()=>validateSettlement(createAuthenticatedValidation({
368
- cartItemsSnapshot: [
369
- {
370
- id: 'item-1',
371
- product: 'product-123',
372
- quantity: 1,
373
- selection: {
374
- variant: null
375
- }
376
- }
377
- ],
378
- transaction: createTransaction({
379
- items: [
380
- {
381
- id: 'item-1',
382
- product: 'product-123',
383
- quantity: 1,
384
- selection: {}
385
- }
386
- ]
387
- })
388
- }))).toThrow('items');
389
- });
390
- it('should preserve nested custom values while ignoring object key order', ()=>{
391
- expect(()=>validateSettlement(createAuthenticatedValidation({
392
- cartItemsSnapshot: [
393
- {
394
- id: 'item-1',
395
- product: 'product-123',
396
- quantity: 1,
397
- selection: {
398
- color: 'blue',
399
- variant: null
400
- }
401
- }
402
- ],
403
- transaction: createTransaction({
404
- items: [
405
- {
406
- id: 'item-1',
407
- product: 'product-123',
408
- quantity: 1,
409
- selection: {
410
- variant: null,
411
- color: 'blue'
412
- }
413
- }
414
- ]
415
- })
416
- }))).not.toThrow();
417
- });
418
- it('should reject malformed item metadata', ()=>{
419
- expect(()=>validateSettlement(createAuthenticatedValidation({
420
- cartItemsSnapshot: {
421
- quantity: 1
422
- }
423
- }))).toThrow('items');
424
- });
425
- it('should reject a PaymentIntent that has not succeeded', ()=>{
426
- expect(()=>validateSettlement(createAuthenticatedValidation({
427
- paymentIntent: createPaymentIntent({
428
- status: 'processing'
429
- })
430
- }))).toThrow('completed');
431
- });
432
- });
433
-
434
- //# sourceMappingURL=validateSettlement.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../../src/payments/adapters/stripe/validateSettlement.spec.ts"],"sourcesContent":["import { describe, expect, it } from 'vitest'\n\nimport {\n getRelationshipID,\n normalizeCartItems,\n normalizeEmail,\n validateSettlement,\n} from './validateSettlement.js'\n\nconst createTransaction = (overrides: Record<string, unknown> = {}) => ({\n amount: 1000,\n cart: 'cart-123',\n currency: 'USD',\n customer: 'user-123',\n id: 'txn-123',\n items: [{ id: 'item-1', product: 'product-123', quantity: 1 }],\n status: 'pending',\n stripe: {\n customerID: 'cus-123',\n paymentIntentID: 'pi_123',\n },\n ...overrides,\n})\n\nconst createPaymentIntent = (overrides: Record<string, unknown> = {}) => ({\n amount: 1000,\n currency: 'usd',\n customer: 'cus-123',\n id: 'pi_123',\n metadata: {\n cartID: 'cart-123',\n },\n status: 'succeeded',\n ...overrides,\n})\n\nconst createAuthenticatedValidation = (overrides: Record<string, unknown> = {}) => ({\n canonicalCartID: 'cart-123',\n cartItemsSnapshot: [{ id: 'item-1', product: 'product-123', quantity: 1 }],\n customerEmail: 'buyer@example.com',\n paymentIntent: createPaymentIntent(),\n paymentIntentID: 'pi_123',\n transaction: createTransaction(),\n user: { id: 'user-123' },\n ...overrides,\n})\n\ndescribe('Stripe settlement normalization', () => {\n it('should extract relationship IDs as strings', () => {\n expect(getRelationshipID({ id: 123 })).toBe('123')\n expect(getRelationshipID(123)).toBe('123')\n expect(getRelationshipID('123')).toBe('123')\n })\n\n it('should reject empty or malformed relationship IDs', () => {\n expect(getRelationshipID('')).toBeUndefined()\n expect(getRelationshipID({ id: '' })).toBeUndefined()\n expect(getRelationshipID({ id: { id: 'nested-id' } })).toBeUndefined()\n })\n\n it('should normalize email case and outer whitespace', () => {\n expect(normalizeEmail(' Buyer@Example.COM ')).toBe('buyer@example.com')\n })\n\n it('should normalize only root relationships while preserving nested custom data', () => {\n expect(\n normalizeCartItems([\n {\n custom: { gift: true },\n product: { id: 123 },\n quantity: 2,\n selections: [{ variant: { id: 'variant-456' } }],\n variant: 456,\n },\n ]),\n ).toEqual([\n {\n custom: { gift: true },\n product: '123',\n quantity: 2,\n selections: [{ variant: { id: 'variant-456' } }],\n variant: '456',\n },\n ])\n })\n})\n\ndescribe('validateSettlement', () => {\n it('should accept a valid authenticated settlement that is pending and unlinked', () => {\n expect(() => validateSettlement(createAuthenticatedValidation())).not.toThrow()\n })\n\n it('should accept a valid guest settlement with normalized emails', () => {\n const transaction = createTransaction({\n customer: undefined,\n customerEmail: ' Buyer@Example.com ',\n })\n\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n customerEmail: 'buyer@example.COM',\n transaction,\n user: undefined,\n }),\n ),\n ).not.toThrow()\n })\n\n it.each([\n { label: 'missing', user: {} },\n { label: 'empty', user: { id: '' } },\n { label: 'malformed', user: { id: {} } },\n ])('should reject a $label ID on a present authenticated principal', ({ user }) => {\n const transaction = createTransaction({\n customer: undefined,\n customerEmail: 'buyer@example.com',\n })\n\n expect(() => validateSettlement(createAuthenticatedValidation({ transaction, user }))).toThrow(\n 'customer',\n )\n })\n\n it('should reject a requested PaymentIntent that does not match the transaction', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n transaction: createTransaction({\n stripe: { customerID: 'cus-123', paymentIntentID: 'pi_other' },\n }),\n }),\n ),\n ).toThrow('PaymentIntent')\n })\n\n it('should reject a canonical cart that does not match the transaction cart', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n transaction: createTransaction({ cart: 'cart-other' }),\n }),\n ),\n ).toThrow('cart')\n })\n\n it('should reject a canonical cart that does not match PaymentIntent metadata', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n paymentIntent: createPaymentIntent({ metadata: { cartID: 'cart-other' } }),\n }),\n ),\n ).toThrow('cart')\n })\n\n it('should reject an authenticated customer that does not own the transaction', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n transaction: createTransaction({ customer: 'user-other' }),\n }),\n ),\n ).toThrow('customer')\n })\n\n it('should reject a guest transaction that belongs to an authenticated customer', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n transaction: createTransaction({ customerEmail: 'buyer@example.com' }),\n user: undefined,\n }),\n ),\n ).toThrow('customer')\n })\n\n it('should reject a guest transaction with a different email', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n transaction: createTransaction({\n customer: undefined,\n customerEmail: 'other@example.com',\n }),\n user: undefined,\n }),\n ),\n ).toThrow('email')\n })\n\n it('should reject a Stripe customer that does not match the transaction', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n paymentIntent: createPaymentIntent({ customer: 'cus-other' }),\n }),\n ),\n ).toThrow('Stripe customer')\n })\n\n it('should reject a Stripe amount that does not match the transaction', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({ paymentIntent: createPaymentIntent({ amount: 999 }) }),\n ),\n ).toThrow('amount')\n })\n\n it('should reject a Stripe currency that does not match after uppercasing', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n paymentIntent: createPaymentIntent({ currency: 'eur' }),\n }),\n ),\n ).toThrow('currency')\n })\n\n it('should reject a lower-case stored transaction currency', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n transaction: createTransaction({ currency: 'usd' }),\n }),\n ),\n ).toThrow('currency')\n })\n\n it('should accept relationship objects and scalar IDs as equivalent item data', () => {\n const transaction = createTransaction({\n items: [{ id: 'item-1', product: { id: 123 }, quantity: 1, variant: { id: 456 } }],\n })\n\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n cartItemsSnapshot: [{ id: 'item-1', product: '123', quantity: 1, variant: '456' }],\n transaction,\n }),\n ),\n ).not.toThrow()\n })\n\n it('should reject an item quantity mismatch', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n cartItemsSnapshot: [{ id: 'item-1', product: 'product-123', quantity: 2 }],\n }),\n ),\n ).toThrow('items')\n })\n\n it('should reject an item custom-property mismatch', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n cartItemsSnapshot: [\n { giftMessage: 'surprise', id: 'item-1', product: 'product-123', quantity: 1 },\n ],\n }),\n ),\n ).toThrow('items')\n })\n\n it('should treat a persisted null root variant as equivalent to an omitted snapshot variant', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n transaction: createTransaction({\n items: [{ id: 'item-1', product: 'product-123', quantity: 1, variant: null }],\n }),\n }),\n ),\n ).not.toThrow()\n })\n\n it('should reject a null root product', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n cartItemsSnapshot: [{ id: 'item-1', product: null, quantity: 1 }],\n }),\n ),\n ).toThrow()\n })\n\n it.each([\n { label: 'malformed object', variant: {} },\n { label: 'blank scalar ID', variant: '' },\n { label: 'blank object ID', variant: { id: '' } },\n { label: 'nested object ID', variant: { id: { id: 'variant-123' } } },\n ])('should reject a $label for a non-null root variant', ({ variant }) => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n cartItemsSnapshot: [{ id: 'item-1', product: 'product-123', quantity: 1, variant }],\n }),\n ),\n ).toThrow()\n })\n\n it('should reject equivalent empty scalar and object relationship IDs', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n cartItemsSnapshot: [{ id: 'item-1', product: 'product-123', quantity: 1, variant: '' }],\n transaction: createTransaction({\n items: [{ id: 'item-1', product: 'product-123', quantity: 1, variant: { id: '' } }],\n }),\n }),\n ),\n ).toThrow()\n })\n\n it('should preserve nested custom variant null when comparing against a missing nested key', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n cartItemsSnapshot: [\n {\n id: 'item-1',\n product: 'product-123',\n quantity: 1,\n selection: { variant: null },\n },\n ],\n transaction: createTransaction({\n items: [{ id: 'item-1', product: 'product-123', quantity: 1, selection: {} }],\n }),\n }),\n ),\n ).toThrow('items')\n })\n\n it('should preserve nested custom values while ignoring object key order', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n cartItemsSnapshot: [\n {\n id: 'item-1',\n product: 'product-123',\n quantity: 1,\n selection: { color: 'blue', variant: null },\n },\n ],\n transaction: createTransaction({\n items: [\n {\n id: 'item-1',\n product: 'product-123',\n quantity: 1,\n selection: { variant: null, color: 'blue' },\n },\n ],\n }),\n }),\n ),\n ).not.toThrow()\n })\n\n it('should reject malformed item metadata', () => {\n expect(() =>\n validateSettlement(createAuthenticatedValidation({ cartItemsSnapshot: { quantity: 1 } })),\n ).toThrow('items')\n })\n\n it('should reject a PaymentIntent that has not succeeded', () => {\n expect(() =>\n validateSettlement(\n createAuthenticatedValidation({\n paymentIntent: createPaymentIntent({ status: 'processing' }),\n }),\n ),\n ).toThrow('completed')\n })\n})\n"],"names":["describe","expect","it","getRelationshipID","normalizeCartItems","normalizeEmail","validateSettlement","createTransaction","overrides","amount","cart","currency","customer","id","items","product","quantity","status","stripe","customerID","paymentIntentID","createPaymentIntent","metadata","cartID","createAuthenticatedValidation","canonicalCartID","cartItemsSnapshot","customerEmail","paymentIntent","transaction","user","toBe","toBeUndefined","custom","gift","selections","variant","toEqual","not","toThrow","undefined","each","label","giftMessage","selection","color"],"mappings":"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"}