@mohasinac/appkit 4.40.1 → 4.41.0
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.
- package/dist/features/categories/repository/categories.repository.js +2 -2
- package/dist/features/tester/seed-data/_money-flows.js +65 -49
- package/dist/features/tester/seed-data/authored/admin__admin-detail-round-trips.js +6 -4
- package/dist/features/tester/seed-data/authored/admin__coupons.js +14 -13
- package/dist/features/tester/seed-data/authored/buying__bidding.js +154 -140
- package/dist/features/tester/seed-data/authored/buying__browsing-search.js +4 -4
- package/dist/features/tester/seed-data/authored/buying__buying-checkout.js +59 -56
- package/dist/features/tester/seed-data/authored/buying__buying-coupons.js +18 -18
- package/dist/features/tester/seed-data/authored/buying__cart.js +105 -79
- package/dist/features/tester/seed-data/authored/buying__image-tile-layout.js +6 -8
- package/dist/features/tester/seed-data/authored/buying__my-orders.js +13 -13
- package/dist/features/tester/seed-data/authored/buying__offers.js +6 -6
- package/dist/features/tester/seed-data/authored/buying__order-detail-actions.js +8 -7
- package/dist/features/tester/seed-data/authored/buying__product-detail.js +62 -56
- package/dist/features/tester/seed-data/authored/buying__return-request.js +6 -6
- package/dist/features/tester/seed-data/authored/buying__reviews-pagination.js +4 -4
- package/dist/features/tester/seed-data/authored/buying__reviews.js +1 -1
- package/dist/features/tester/seed-data/authored/buying__user-dashboard-extras.js +8 -8
- package/dist/features/tester/seed-data/authored/content-discovery__category-counts-and-rollup.js +1 -1
- package/dist/features/tester/seed-data/authored/content-discovery__coupons.js +29 -16
- package/dist/features/tester/seed-data/authored/content-discovery__event-detail-subroutes.js +9 -9
- package/dist/features/tester/seed-data/authored/content-discovery__events.js +69 -36
- package/dist/features/tester/seed-data/authored/content-discovery__notifications.js +1 -1
- package/dist/features/tester/seed-data/authored/cta-layout__checkout-bottom-bar.js +2 -2
- package/dist/features/tester/seed-data/authored/design-ux__back-to-top-button.js +2 -2
- package/dist/features/tester/seed-data/authored/design-ux__general-design.js +1 -1
- package/dist/features/tester/seed-data/authored/design-ux__status-badge-legibility.js +1 -1
- package/dist/features/tester/seed-data/authored/design-ux__sticky-cta-bar.js +3 -3
- package/dist/features/tester/seed-data/authored/index.js +0 -2
- package/dist/features/tester/seed-data/authored/page-wiring__data-loss.js +2 -2
- package/dist/features/tester/seed-data/authored/page-wiring__reachability.js +6 -4
- package/dist/features/tester/seed-data/authored/public-pages__auth-error-pages.js +2 -2
- package/dist/features/tester/seed-data/authored/public-pages__core-listing-pages.js +1 -1
- package/dist/features/tester/seed-data/authored/public-pages__stores-sellers-directories.js +8 -10
- package/dist/features/tester/seed-data/authored/selling__become-seller.js +2 -2
- package/dist/features/tester/seed-data/authored/selling__digital-content-delivery.js +2 -2
- package/dist/features/tester/seed-data/authored/selling__listing-a-product.js +2 -2
- package/dist/features/tester/seed-data/authored/selling__listing-edit-roundtrip.js +2 -2
- package/dist/features/tester/seed-data/authored/selling__listing-lifecycle.js +2 -2
- package/dist/features/tester/seed-data/authored/selling__seller-listing-types.js +2 -2
- package/dist/features/tester/seed-data/authored/seo__og-images.js +3 -4
- package/dist/features/tester/seed-data/authored/seo__page-metadata.js +6 -8
- package/dist/features/tester/seed-data/authored/seo__sitemap-and-robots.js +5 -5
- package/dist/features/tester/seed-data/index.d.ts +0 -10
- package/dist/features/tester/seed-data/index.js +0 -10
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +75 -89
- package/dist/features/tester/seed-data/tester-responses-seed-data.js +5 -5
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -21
- package/dist/seed/addresses-seed-data.js +0 -34
- package/dist/seed/index.d.ts +1 -1
- package/dist/seed/index.js +4 -3
- package/dist/seed/manifest.js +11 -12
- package/dist/seed/notifications-seed-data.js +4 -4
- package/dist/seed/stores-seed-data.js +7 -52
- package/dist/seed/users-seed-data.js +3 -83
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +15 -20
|
@@ -412,8 +412,8 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
412
412
|
*
|
|
413
413
|
* 🛑 MEASURED 2026-09-14: `category` is unset on all 95 production products.
|
|
414
414
|
* It is written by deriveTaxonomy, but every product here came from the seed,
|
|
415
|
-
* which hand-writes `categorySlugs` only — so
|
|
416
|
-
*
|
|
415
|
+
* which hand-writes `categorySlugs` only — so an equality query on that
|
|
416
|
+
* scalar matched nothing and this rewrite silently did nothing at all. The
|
|
417
417
|
* array field is the one that actually exists, and matching the MOVED node
|
|
418
418
|
* gets the entire subtree in a single read because `categorySlugs` holds the
|
|
419
419
|
* full ancestor chain.
|
|
@@ -28,23 +28,23 @@ export const moneyFlowsPages = [
|
|
|
28
28
|
{
|
|
29
29
|
pageKey: "offer-to-purchase",
|
|
30
30
|
pageLabel: "Offer → accept → pay",
|
|
31
|
-
href: "/products/product-
|
|
31
|
+
href: "/products/product-beyblade-burst-valkyrie",
|
|
32
32
|
cases: [
|
|
33
33
|
{
|
|
34
34
|
key: "buyer-makes-offer",
|
|
35
35
|
label: "A buyer can make an offer on a seller's product and it appears in their own offers list",
|
|
36
36
|
roles: ["buyer"],
|
|
37
|
-
startPage: "/products/product-
|
|
37
|
+
startPage: "/products/product-beyblade-burst-valkyrie",
|
|
38
38
|
steps: [
|
|
39
39
|
STEP_SIGNIN_BUYER,
|
|
40
|
-
"Open /products/product-
|
|
40
|
+
"Open /products/product-beyblade-burst-valkyrie.",
|
|
41
41
|
"Click 'Make Offer'.",
|
|
42
42
|
"Enter 780 as the offer amount.",
|
|
43
43
|
"Enter the note 'QA offer offer-to-purchase-buyer-makes-offer'.",
|
|
44
44
|
"Click 'Submit offer'.",
|
|
45
45
|
"Open /user/offers.",
|
|
46
46
|
],
|
|
47
|
-
expectedBehaviour: "An offer is created for 780 against product-
|
|
47
|
+
expectedBehaviour: "An offer is created for 780 against product-beyblade-burst-valkyrie, owned by the signed-in buyer, and the owning seller receives an offer-received notification.",
|
|
48
48
|
expectedUiState: "The offer modal closes and a success confirmation appears. /user/offers lists a row for the product with amount ₹780 and status Pending. The page does NOT read 'No offers yet'.",
|
|
49
49
|
endResult: "After reloading /user/offers the row is still listed at ₹780 with status Pending.",
|
|
50
50
|
},
|
|
@@ -52,10 +52,10 @@ export const moneyFlowsPages = [
|
|
|
52
52
|
key: "duplicate-offer-refused",
|
|
53
53
|
label: "A second offer on the same listing while one is still pending is refused",
|
|
54
54
|
roles: ["buyer"],
|
|
55
|
-
startPage: "/products/product-
|
|
55
|
+
startPage: "/products/product-beyblade-burst-valkyrie",
|
|
56
56
|
steps: [
|
|
57
57
|
"Sign in as the buyer ash@pokemonpalace.in, holding the pending 780 offer from the previous case.",
|
|
58
|
-
"Open /products/product-
|
|
58
|
+
"Open /products/product-beyblade-burst-valkyrie.",
|
|
59
59
|
"Click 'Make Offer'.",
|
|
60
60
|
"Enter 800 as the offer amount.",
|
|
61
61
|
"Click 'Submit offer'.",
|
|
@@ -70,15 +70,15 @@ export const moneyFlowsPages = [
|
|
|
70
70
|
roles: ["seller"],
|
|
71
71
|
startPage: "/store/offers",
|
|
72
72
|
steps: [
|
|
73
|
-
"Sign in as
|
|
73
|
+
"Sign in as tyson@beybladearena.in / TempPass123!, who owns store-beyblade-arena.",
|
|
74
74
|
"Open /store/offers.",
|
|
75
|
-
"Find the row for offer-
|
|
75
|
+
"Find the row for offer-yugi-burst-valkyrie-pending (product-beyblade-burst-valkyrie, offered ₹780 against a listed ₹999).",
|
|
76
76
|
"Open the row actions menu.",
|
|
77
77
|
"Click 'Accept'.",
|
|
78
78
|
"Confirm in the dialog.",
|
|
79
79
|
"Reload /store/offers.",
|
|
80
80
|
],
|
|
81
|
-
expectedBehaviour: "The offer moves to Accepted, a locked price of
|
|
81
|
+
expectedBehaviour: "The offer moves to Accepted, a locked price of 780 is recorded, and the buyer receives an offer-responded notification.",
|
|
82
82
|
expectedUiState: "Before acting, the row menu offers Accept, Decline and Counter as enabled controls. After confirming, the row's status badge reads Accepted.",
|
|
83
83
|
endResult: "After reloading /store/offers the status still reads Accepted — not Pending.",
|
|
84
84
|
href: "/store/offers",
|
|
@@ -89,15 +89,15 @@ export const moneyFlowsPages = [
|
|
|
89
89
|
roles: ["buyer"],
|
|
90
90
|
startPage: "/user/offers",
|
|
91
91
|
steps: [
|
|
92
|
-
"Sign in as
|
|
92
|
+
"Sign in as vivaan.kapoor@gmail.com / TempPass123!, who holds offer-kaiba-dranzer-s-accepted on product-beyblade-original-dranzer-s (listed ₹1499, agreed ₹1250).",
|
|
93
93
|
"Open /user/offers.",
|
|
94
94
|
"Click through to checkout from the accepted offer.",
|
|
95
95
|
"Read the line item price in the checkout summary.",
|
|
96
96
|
"Continue to the payment step.",
|
|
97
97
|
"Read the order total.",
|
|
98
98
|
],
|
|
99
|
-
expectedBehaviour: "Every price computed for this line uses the locked
|
|
100
|
-
expectedUiState: "The line item reads ₹
|
|
99
|
+
expectedBehaviour: "Every price computed for this line uses the locked 1250, not the product's current 1499.",
|
|
100
|
+
expectedUiState: "The line item reads ₹1,250.00 and the order total reflects 1250 plus fees. ₹1,499 appears nowhere on the checkout screen for this line.",
|
|
101
101
|
endResult: "Nothing is placed in this case — stop at the payment step. The check is that the two numbers never appear together for the same line.",
|
|
102
102
|
href: "/user/offers",
|
|
103
103
|
},
|
|
@@ -105,16 +105,16 @@ export const moneyFlowsPages = [
|
|
|
105
105
|
key: "owning-seller-cannot-offer",
|
|
106
106
|
label: "The owning seller sees no Make Offer control on their own listing",
|
|
107
107
|
roles: ["seller"],
|
|
108
|
-
startPage: "/products/product-
|
|
108
|
+
startPage: "/products/product-beyblade-burst-valkyrie",
|
|
109
109
|
steps: [
|
|
110
|
-
"Sign in as
|
|
111
|
-
"Open /products/product-
|
|
110
|
+
"Sign in as tyson@beybladearena.in / TempPass123!, who owns store-beyblade-arena.",
|
|
111
|
+
"Open /products/product-beyblade-burst-valkyrie, a listing owned by that store.",
|
|
112
112
|
"Read the action controls on the listing.",
|
|
113
113
|
],
|
|
114
114
|
expectedBehaviour: "The seller is not offered any purchase path on their own listing — you cannot make an offer on, or buy, your own item.",
|
|
115
115
|
expectedUiState: "'Make Offer' is ABSENT, not merely disabled. A seller-facing control such as 'Edit listing' is shown instead.",
|
|
116
116
|
endResult: "Nothing is persisted; this is a read-only check of which controls render for the owner.",
|
|
117
|
-
href: "/products/product-
|
|
117
|
+
href: "/products/product-beyblade-burst-valkyrie",
|
|
118
118
|
},
|
|
119
119
|
{
|
|
120
120
|
key: "offer-lane-blocks-other-items",
|
|
@@ -122,8 +122,9 @@ export const moneyFlowsPages = [
|
|
|
122
122
|
roles: ["buyer"],
|
|
123
123
|
startPage: "/cart",
|
|
124
124
|
steps: [
|
|
125
|
-
"Sign in as
|
|
126
|
-
"Open /
|
|
125
|
+
"Sign in as vivaan.kapoor@gmail.com / TempPass123!, who holds offer-kaiba-dranzer-s-accepted.",
|
|
126
|
+
"Open /user/offers and start checkout from that accepted offer so its locked line enters the cart, then return to /products.",
|
|
127
|
+
"Open /products/product-beyblade-burst-valkyrie and click 'Add to cart'.",
|
|
127
128
|
"Open /cart.",
|
|
128
129
|
"Read which lane or tab each line sits in.",
|
|
129
130
|
"Attempt to check out the standard item.",
|
|
@@ -135,17 +136,17 @@ export const moneyFlowsPages = [
|
|
|
135
136
|
},
|
|
136
137
|
{
|
|
137
138
|
key: "expired-offer-cannot-checkout",
|
|
138
|
-
label: "An
|
|
139
|
+
label: "An offer past its window can no longer be paid",
|
|
139
140
|
roles: ["buyer"],
|
|
140
141
|
startPage: "/user/offers",
|
|
141
142
|
steps: [
|
|
142
|
-
"Sign in as
|
|
143
|
-
"Open /user/offers and find offer-
|
|
144
|
-
"
|
|
145
|
-
"
|
|
143
|
+
"Sign in as vivaan.kapoor@gmail.com / TempPass123!.",
|
|
144
|
+
"Open /user/offers and find offer-kaiba-x-wizard-arrow-expired (product-beyblade-x-wizard-arrow, ₹700), whose window closed two days ago.",
|
|
145
|
+
"Read the row's status badge and the date it names.",
|
|
146
|
+
"Read every control the row offers.",
|
|
146
147
|
"Attempt to start checkout from that offer.",
|
|
147
148
|
],
|
|
148
|
-
expectedBehaviour: "Checkout is refused once the
|
|
149
|
+
expectedBehaviour: "Checkout is refused once the window has passed; the offer is treated as expired rather than payable.",
|
|
149
150
|
expectedUiState: "The row reads Expired and offers no checkout control. It must not silently proceed at ₹700.",
|
|
150
151
|
endResult: "After reloading /user/offers the row still reads Expired.",
|
|
151
152
|
href: "/user/offers",
|
|
@@ -165,7 +166,7 @@ export const moneyFlowsPages = [
|
|
|
165
166
|
// seed-data/fixtures/money-flows__auction-win-to-payment.mjs and closing
|
|
166
167
|
// ~3 minutes after this batch starts.
|
|
167
168
|
//
|
|
168
|
-
// It used to cite auction-
|
|
169
|
+
// It used to cite auction-beyblade-original-dragoon-storm, which 46 OTHER
|
|
169
170
|
// citations need LIVE — one fixture with two contradictory
|
|
170
171
|
// requirements, so this case could never pass its final step and the
|
|
171
172
|
// rig notes recorded it as unpassable-by-design.
|
|
@@ -261,10 +262,10 @@ export const moneyFlowsPages = [
|
|
|
261
262
|
key: "cod-order-places",
|
|
262
263
|
label: "A cash-on-delivery order can be placed and shows the COD fee before confirming",
|
|
263
264
|
roles: ["buyer"],
|
|
264
|
-
startPage: "/products/product-
|
|
265
|
+
startPage: "/products/product-beyblade-burst-valkyrie",
|
|
265
266
|
steps: [
|
|
266
267
|
STEP_SIGNIN_BUYER,
|
|
267
|
-
"Open /products/product-
|
|
268
|
+
"Open /products/product-beyblade-burst-valkyrie and click 'Add to cart'.",
|
|
268
269
|
"Open /checkout and complete the address step.",
|
|
269
270
|
"Continue to the add-ons and fees step.",
|
|
270
271
|
"Select 'Cash on Delivery'.",
|
|
@@ -282,7 +283,7 @@ export const moneyFlowsPages = [
|
|
|
282
283
|
roles: ["buyer"],
|
|
283
284
|
startPage: "/checkout",
|
|
284
285
|
steps: [
|
|
285
|
-
"Sign in as the buyer ash@pokemonpalace.in with product-
|
|
286
|
+
"Sign in as the buyer ash@pokemonpalace.in with product-beyblade-original-dranzer-s in the cart.",
|
|
286
287
|
"Open /checkout and complete the address step.",
|
|
287
288
|
"Select UPI / manual payment.",
|
|
288
289
|
STEP_PLACE_ORDER,
|
|
@@ -319,8 +320,8 @@ export const moneyFlowsPages = [
|
|
|
319
320
|
startPage: "/checkout",
|
|
320
321
|
steps: [
|
|
321
322
|
STEP_SIGNIN_BUYER,
|
|
322
|
-
"Add product-tester-standard-1 (store-tester-sandbox) to the cart.",
|
|
323
323
|
"Add product-beyblade-burst-valkyrie (store-beyblade-arena) to the cart.",
|
|
324
|
+
"Add prizedraw-beyblade-mystery-box (store-letitrip-official) to the cart, so the cart spans two sellers.",
|
|
324
325
|
"Open /checkout and reach the payment step.",
|
|
325
326
|
"Write down the exact total and every fee line.",
|
|
326
327
|
STEP_PLACE_ORDER,
|
|
@@ -359,63 +360,78 @@ export const moneyFlowsPages = [
|
|
|
359
360
|
key: "out-of-stock-blocked",
|
|
360
361
|
label: "A sold-out item cannot be added to the cart or checked out",
|
|
361
362
|
roles: ["buyer"],
|
|
362
|
-
startPage: "/products/product-
|
|
363
|
+
startPage: "/products/product-beyblade-burst-valtryek-v3-sold-out",
|
|
363
364
|
steps: [
|
|
364
365
|
STEP_SIGNIN_BUYER,
|
|
365
|
-
"Open /products/product-
|
|
366
|
+
"Open /products/product-beyblade-burst-valtryek-v3-sold-out, a deliberately sold-out fixture.",
|
|
366
367
|
"Attempt to add it to the cart.",
|
|
367
368
|
],
|
|
368
369
|
expectedBehaviour: "The add is refused and no cart line is created for an unavailable item.",
|
|
369
370
|
expectedUiState: "The add control is disabled or replaced by a Sold Out state, with the reason stated on the page.",
|
|
370
371
|
endResult: "After reloading /cart the item is absent.",
|
|
371
|
-
href: "/products/product-
|
|
372
|
+
href: "/products/product-beyblade-burst-valtryek-v3-sold-out",
|
|
372
373
|
},
|
|
373
374
|
{
|
|
375
|
+
/*
|
|
376
|
+
* 🛑 THIS CASE MOVED FROM THE CART TO THE BUNDLE EDITOR, 2026-09-15.
|
|
377
|
+
*
|
|
378
|
+
* It used to open a deliberately-banned pair of fixtures — two products
|
|
379
|
+
* in different stores wired into one group — and assert that the cart's
|
|
380
|
+
* picker refused them. Those fixtures are gone, and no replacement can
|
|
381
|
+
* be seeded: the guard the case tests is applied at SAVE time, so a
|
|
382
|
+
* cross-store group cannot exist to be opened.
|
|
383
|
+
*
|
|
384
|
+
* The refusal is therefore tested where it actually fires — an admin
|
|
385
|
+
* ATTEMPTS the banned shape and is refused before it is stored.
|
|
386
|
+
*/
|
|
374
387
|
key: "cross-store-group-refused",
|
|
375
|
-
label: "A
|
|
376
|
-
roles: ["
|
|
377
|
-
startPage: "/
|
|
388
|
+
label: "A bundle whose members span two stores is refused when saved",
|
|
389
|
+
roles: ["admin"],
|
|
390
|
+
startPage: "/admin/bundles",
|
|
378
391
|
steps: [
|
|
379
|
-
|
|
380
|
-
"Open /
|
|
381
|
-
"
|
|
382
|
-
"
|
|
392
|
+
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
393
|
+
"Open /admin/bundles and start a new bundle.",
|
|
394
|
+
"Name it 'QA cross-store bundle'.",
|
|
395
|
+
"Add product-beyblade-burst-valkyrie (store-beyblade-arena) as a member.",
|
|
396
|
+
"Add prizedraw-beyblade-mystery-box (store-letitrip-official) as a second member — a different store.",
|
|
397
|
+
"Set the bundle price to 1000 and click Save.",
|
|
383
398
|
],
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
399
|
+
inputs: { bundleName: "QA cross-store bundle", bundlePrice: 1000 },
|
|
400
|
+
expectedBehaviour: "The save is refused because an order belongs to exactly one seller, and a bundle spanning two stores would produce an order containing another seller's product — with no notification, no shipping resolution and no payout for that second seller. The refusal is at save time, not at add-to-cart time, so bundles already stored keep working.",
|
|
401
|
+
expectedUiState: "An error names the two stores, or at least states that a bundle cannot span sellers. The editor stays open with the entered members intact rather than clearing.",
|
|
402
|
+
endResult: "After reloading /admin/bundles there is no bundle named 'QA cross-store bundle'.",
|
|
403
|
+
href: "/admin/bundles",
|
|
388
404
|
},
|
|
389
405
|
{
|
|
390
406
|
key: "classified-has-no-cart",
|
|
391
407
|
label: "A classified listing offers contact, never Add to Cart",
|
|
392
408
|
roles: ["buyer"],
|
|
393
|
-
startPage: "/classified/classified-
|
|
409
|
+
startPage: "/classified/classified-beyblade-stadium-set",
|
|
394
410
|
steps: [
|
|
395
411
|
STEP_SIGNIN_BUYER,
|
|
396
|
-
"Open /classified/classified-
|
|
412
|
+
"Open /classified/classified-beyblade-stadium-set.",
|
|
397
413
|
"Read every action control on the listing.",
|
|
398
414
|
],
|
|
399
415
|
expectedBehaviour: "A classified is a contact-only listing type with no cart path at all.",
|
|
400
416
|
expectedUiState: "Exactly one of 'Make Offer', 'Request to Buy' or a contact-seller control is present. 'Add to Cart' and 'Buy Now' are ABSENT, not disabled.",
|
|
401
417
|
endResult: "Nothing is persisted; this is a read-only check of which controls render.",
|
|
402
|
-
href: "/classified/classified-
|
|
418
|
+
href: "/classified/classified-beyblade-stadium-set",
|
|
403
419
|
},
|
|
404
420
|
{
|
|
405
421
|
key: "guest-gated-action-prompts-signin",
|
|
406
422
|
label: "A gated action while signed out prompts sign-in and then completes the original action",
|
|
407
423
|
roles: ["guest"],
|
|
408
|
-
startPage: "/products/product-
|
|
424
|
+
startPage: "/products/product-beyblade-burst-valkyrie",
|
|
409
425
|
steps: [
|
|
410
426
|
"Sign out completely.",
|
|
411
|
-
"Open /products/product-
|
|
427
|
+
"Open /products/product-beyblade-burst-valkyrie.",
|
|
412
428
|
"Click the wishlist heart.",
|
|
413
429
|
"Sign in as ash@pokemonpalace.in through the prompt that appears.",
|
|
414
430
|
],
|
|
415
431
|
expectedBehaviour: "The click is held while signing in and then replayed, so the item ends up on the wishlist.",
|
|
416
432
|
expectedUiState: "A sign-in prompt appears rather than the click doing nothing. After signing in, the heart shows the saved state.",
|
|
417
433
|
endResult: "After reloading /wishlist the item is listed.",
|
|
418
|
-
href: "/products/product-
|
|
434
|
+
href: "/products/product-beyblade-burst-valkyrie",
|
|
419
435
|
},
|
|
420
436
|
{
|
|
421
437
|
key: "banned-account-blocked",
|
|
@@ -79,18 +79,20 @@ export const authored = {
|
|
|
79
79
|
startPage: "/admin/users",
|
|
80
80
|
steps: [
|
|
81
81
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
82
|
-
"Open /admin/users and find the account
|
|
83
|
-
"Open its Edit action and
|
|
82
|
+
"Open /admin/users and find the account rehan.sheikh@gmail.com.",
|
|
83
|
+
"Open its Edit action, turn BOTH tester flags on, and save — no seeded account carries them, so the case has to set up the field it is about.",
|
|
84
|
+
"Reopen the same account and confirm both flags read as on.",
|
|
84
85
|
"Change ONLY its bio — append the word roundtrip.",
|
|
85
86
|
"Press Save.",
|
|
86
87
|
"Reload the list and reopen the same account.",
|
|
87
88
|
"Read the tester flags again.",
|
|
89
|
+
"Turn both tester flags back off and save.",
|
|
88
90
|
],
|
|
89
|
-
inputs: { account: "
|
|
91
|
+
inputs: { account: "rehan.sheikh@gmail.com", bioSuffix: "roundtrip" },
|
|
90
92
|
expectedBehaviour: "An editor seeded from a LIST row can only send back what that row carried. If the list serializer omits a field the update schema accepts, the editor state defaults to false and the save rewrites it — so editing any other field silently strips it. That is why the check is on a field the form did not touch.",
|
|
91
93
|
expectedUiState: "Both tester flags are still on after the reload, and the bio carries the appended word.",
|
|
92
94
|
expectedData: { testerFlagsPreserved: true },
|
|
93
|
-
endResult: "The flags survive a second reload
|
|
95
|
+
endResult: "The flags survive a second reload, and the final step leaves the account back on its seeded settings with both flags off.",
|
|
94
96
|
},
|
|
95
97
|
"checklist-admin-admin-detail-round-trips-store-edit-keeps-verified": {
|
|
96
98
|
roles: ["admin"],
|
|
@@ -62,14 +62,14 @@ export const authored = {
|
|
|
62
62
|
startPage: "/admin/coupons",
|
|
63
63
|
steps: [
|
|
64
64
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
65
|
-
"Open /admin/coupons, find
|
|
66
|
-
"Sign in as vivaan.kapoor@gmail.com / TempPass123! and place an order applying
|
|
65
|
+
"Open /admin/coupons, find ARENAVIP, and read its per-user limit (1), total limit (50) and current usage (12).",
|
|
66
|
+
"Sign in as vivaan.kapoor@gmail.com / TempPass123! and place an order of 2 × product-beyblade-original-dranzer-s (₹2,998, above ARENAVIP's ₹2,000 minimum) applying ARENAVIP.",
|
|
67
67
|
"Attempt a second order applying it again and read the refusal.",
|
|
68
|
-
"Sign in as rehan.sheikh@gmail.com / TempPass123! and apply
|
|
68
|
+
"Sign in as rehan.sheikh@gmail.com / TempPass123! and apply ARENAVIP at checkout on the same two items.",
|
|
69
69
|
"Sign back in as admin and read the usage count.",
|
|
70
70
|
],
|
|
71
|
-
inputs: { code: "
|
|
72
|
-
expectedBehaviour: "
|
|
71
|
+
inputs: { code: "ARENAVIP", perUserLimit: 1 },
|
|
72
|
+
expectedBehaviour: "ARENAVIP is one use per user, and its total limit of 50 has 38 uses left — so exhausting it for one buyer must leave it usable by the next. Enforcing a per-user limit as if it were global withdraws the coupon from everybody after a single redemption.",
|
|
73
73
|
expectedUiState: "The same buyer's second attempt is refused with a limit message. A DIFFERENT buyer's attempt is accepted. The admin usage count has risen by the number of redemptions, and the coupon still reads as active.",
|
|
74
74
|
expectedData: { perUserLimit: 1 },
|
|
75
75
|
endResult: "The cross-account half is the case — the same-account half alone passes under either reading.",
|
|
@@ -80,7 +80,7 @@ export const authored = {
|
|
|
80
80
|
steps: [
|
|
81
81
|
"Sign in as admin@letitrip.in / TempPass123! and confirm QAADMIN15 has a minimum purchase of 500 and a maximum discount of 200.",
|
|
82
82
|
"Sign in as vivaan.kapoor@gmail.com / TempPass123!.",
|
|
83
|
-
"Add product-
|
|
83
|
+
"Add product-beyblade-metal-storm-pegasus (₹99) to the cart alone and apply QAADMIN15 at checkout.",
|
|
84
84
|
"Read the refusal and whether it names the required amount.",
|
|
85
85
|
"Add product-beyblade-original-driger-v (₹1,799) so the subtotal clears the minimum, and apply again.",
|
|
86
86
|
"Read the discount amount.",
|
|
@@ -111,17 +111,18 @@ export const authored = {
|
|
|
111
111
|
startPage: "/admin/coupons",
|
|
112
112
|
steps: [
|
|
113
113
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
114
|
-
"Open /admin/coupons and
|
|
115
|
-
"
|
|
116
|
-
"Sign in as vivaan.kapoor@gmail.com / TempPass123! and apply
|
|
114
|
+
"Open /admin/coupons, open SEALED20, and write down its end date.",
|
|
115
|
+
"Set its end date to yesterday and LEAVE the Active toggle ON, then save — it is now past its end date while still flagged active.",
|
|
116
|
+
"Sign in as vivaan.kapoor@gmail.com / TempPass123! and apply SEALED20 at checkout.",
|
|
117
117
|
"Read the exact wording of the refusal.",
|
|
118
|
-
"Sign back in as admin, deactivate
|
|
118
|
+
"Sign back in as admin, deactivate BLADER50 without touching its dates, and apply that one as the buyer.",
|
|
119
119
|
"Compare the two refusal messages.",
|
|
120
|
+
"Sign back in as admin, restore SEALED20's end date and reactivate BLADER50.",
|
|
120
121
|
],
|
|
121
|
-
inputs: { expiredCode: "
|
|
122
|
-
expectedBehaviour: "Expiry and deactivation are two separate reasons and both refuse.
|
|
122
|
+
inputs: { expiredCode: "SEALED20", deactivatedCode: "BLADER50" },
|
|
123
|
+
expectedBehaviour: "Expiry and deactivation are two separate reasons and both refuse. SEALED20 is pushed past its end date while still flagged active precisely so the DATE check is exercised rather than the flag — a validator reading only the flag would accept it.",
|
|
123
124
|
expectedUiState: "The expired coupon is refused with a message naming expiry. The deactivated one is refused with a different message. Two identical generic refusals mean only one of the two checks is running.",
|
|
124
|
-
endResult: "
|
|
125
|
+
endResult: "SEALED20's end date is restored and BLADER50 is reactivated by the final step. Leaving either changed silently breaks every later case that applies them.",
|
|
125
126
|
},
|
|
126
127
|
"checklist-admin-coupons-coupon-admin-is-platform-wide": {
|
|
127
128
|
roles: ["admin", "buyer"],
|