max / makenotwork
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
1 file changed,
+74 insertions,
-4 deletions
| @@ -1247,15 +1247,85 @@ | |||
| 1247 | 1247 | "Should have created a checkout session" | |
| 1248 | 1248 | ); | |
| 1249 | 1249 | ||
| 1250 | - | // Verify pending transaction | |
| 1251 | - | let count: i64 = sqlx::query_scalar( | |
| 1252 | - | "SELECT COUNT(*) FROM transactions WHERE buyer_id = $1 AND status = 'pending'", | |
| 1250 | + | // Verify pending transaction: one row, at the item's price. | |
| 1251 | + | let (count, total): (i64, i64) = sqlx::query_as( | |
| 1252 | + | "SELECT COUNT(*), COALESCE(SUM(amount_cents), 0) FROM transactions \ | |
| 1253 | + | WHERE buyer_id = $1 AND status = 'pending'", | |
| 1253 | 1254 | ) | |
| 1254 | 1255 | .bind(buyer_id) | |
| 1255 | 1256 | .fetch_one(&h.db) | |
| 1256 | 1257 | .await | |
| 1257 | 1258 | .unwrap(); | |
| 1258 | - | assert!(count >= 1, "Should have at least 1 pending transaction"); | |
| 1259 | + | assert_eq!(count, 1, "one pending transaction for a one-item cart"); | |
| 1260 | + | assert_eq!(total, 500, "pending amount must be the item's price"); | |
| 1261 | + | } | |
| 1262 | + | ||
| 1263 | + | /// Two paid items from the same seller in one cart produce one pending | |
| 1264 | + | /// transaction per item, and their amounts sum to the cart total. Pins the | |
| 1265 | + | /// cart core's per-line insert against a single-row shortcut. | |
| 1266 | + | #[tokio::test] | |
| 1267 | + | async fn cart_checkout_two_items_same_seller_sums_to_cart_total() { | |
| 1268 | + | let mut h = TestHarness::with_mocks().await; | |
| 1269 | + | let (seller_id, project_id, item_a) = setup_paid_item(&mut h, 500).await; | |
| 1270 | + | ||
| 1271 | + | // Second paid item under the same seller and project. | |
| 1272 | + | h.login("seller", "pass1234").await; | |
| 1273 | + | let resp = h | |
| 1274 | + | .client | |
| 1275 | + | .post_form( | |
| 1276 | + | &format!("/api/projects/{project_id}/items"), | |
| 1277 | + | "title=Second+Track&price_cents=250&item_type=audio", | |
| 1278 | + | ) | |
| 1279 | + | .await; | |
| 1280 | + | assert_eq!(resp.status, 200, "create second item failed: {}", resp.text); | |
| 1281 | + | let second: Value = resp.json(); | |
| 1282 | + | let item_b = second["id"].as_str().unwrap().to_string(); | |
| 1283 | + | h.client | |
| 1284 | + | .put_form(&format!("/api/items/{item_b}"), "is_public=true") | |
| 1285 | + | .await; | |
| 1286 | + | h.client.post_form("/logout", "").await; | |
| 1287 | + | ||
| 1288 | + | let buyer_id = h.signup("cartsum", "cartsum@test.com", "pass1234").await; | |
| 1289 | + | h.client.post_form(&format!("/api/cart/{item_a}"), "").await; | |
| 1290 | + | h.client.post_form(&format!("/api/cart/{item_b}"), "").await; | |
| 1291 | + | ||
| 1292 | + | let resp = h | |
| 1293 | + | .client | |
| 1294 | + | .post_form( | |
| 1295 | + | "/stripe/checkout/cart", | |
| 1296 | + | &format!("seller_id={seller_id}&share_contact=false"), | |
| 1297 | + | ) | |
| 1298 | + | .await; | |
| 1299 | + | assert_eq!( | |
| 1300 | + | resp.status, 303, | |
| 1301 | + | "two-item cart checkout should redirect: {} {}", | |
| 1302 | + | resp.status, resp.text | |
| 1303 | + | ); | |
| 1304 | + | ||
| 1305 | + | let (count, total): (i64, i64) = sqlx::query_as( | |
| 1306 | + | "SELECT COUNT(*), COALESCE(SUM(amount_cents), 0) FROM transactions \ | |
| 1307 | + | WHERE buyer_id = $1 AND status = 'pending'", | |
| 1308 | + | ) | |
| 1309 | + | .bind(buyer_id) | |
| 1310 | + | .fetch_one(&h.db) | |
| 1311 | + | .await | |
| 1312 | + | .unwrap(); | |
| 1313 | + | assert_eq!(count, 2, "one pending row per paid cart line"); | |
| 1314 | + | assert_eq!( | |
| 1315 | + | total, 750, | |
| 1316 | + | "pending amounts must sum to the two items' combined price" | |
| 1317 | + | ); | |
| 1318 | + | ||
| 1319 | + | // Both rows belong to one Stripe session: the cart is charged once. | |
| 1320 | + | let sessions: i64 = sqlx::query_scalar( | |
| 1321 | + | "SELECT COUNT(DISTINCT stripe_checkout_session_id) FROM transactions \ | |
| 1322 | + | WHERE buyer_id = $1 AND status = 'pending'", | |
| 1323 | + | ) | |
| 1324 | + | .bind(buyer_id) | |
| 1325 | + | .fetch_one(&h.db) | |
| 1326 | + | .await | |
| 1327 | + | .unwrap(); | |
| 1328 | + | assert_eq!(sessions, 1, "a cart checkout is one Stripe session"); | |
| 1259 | 1329 | } | |
| 1260 | 1330 | ||
| 1261 | 1331 | #[tokio::test] |