@mohasinac/appkit 4.42.1 → 4.42.2
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/_internal/server/features/offers/adapters.d.ts +29 -7
- package/dist/_internal/server/features/offers/adapters.js +14 -3
- package/dist/_internal/server/features/orders/adapters.js +54 -1
- package/dist/client.d.ts +1 -0
- package/dist/client.js +1 -0
- package/dist/features/account/components/UserOrdersView.js +30 -2
- package/dist/features/account/hooks/useAddresses.d.ts +21 -6
- package/dist/features/account/hooks/useAddresses.js +1 -1
- package/dist/features/addresses/hooks/usePostalLookup.js +84 -12
- package/dist/features/admin/components/AdminCategoriesView.js +37 -2
- package/dist/features/admin/components/AdminOffersView.js +2 -2
- package/dist/features/admin/constants/filter-tabs.d.ts +25 -0
- package/dist/features/admin/constants/filter-tabs.js +30 -0
- package/dist/features/admin/hooks/useAdminListingData.d.ts +35 -0
- package/dist/features/admin/hooks/useAdminListingData.js +45 -9
- package/dist/features/cart/schemas/index.d.ts +15 -0
- package/dist/features/cart/schemas/index.js +2 -0
- package/dist/features/cart/types/index.d.ts +22 -0
- package/dist/features/categories/components/CategoriesIndexListing.js +19 -1
- package/dist/features/categories/components/CategoriesIndexPageView.js +14 -1
- package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +8 -0
- package/dist/features/classified/components/ClassifiedDetailPageView.js +1 -0
- package/dist/features/events/actions/event-actions.d.ts +13 -0
- package/dist/features/events/actions/event-actions.js +75 -1
- package/dist/features/events/repository/event-entry.repository.d.ts +17 -0
- package/dist/features/events/repository/event-entry.repository.js +36 -0
- package/dist/features/homepage/components/BrandsSection.js +1 -1
- package/dist/features/homepage/components/CustomerReviewsSection.js +1 -1
- package/dist/features/homepage/components/FeaturedBundlesSection.js +1 -1
- package/dist/features/homepage/components/ShopByCategorySection.js +1 -1
- package/dist/features/media/upload/MediaUploadField.js +21 -3
- package/dist/features/orders/components/OrdersList.js +2 -1
- package/dist/features/orders/index.d.ts +1 -0
- package/dist/features/orders/index.js +1 -0
- package/dist/features/orders/types/index.d.ts +2 -0
- package/dist/features/orders/utils/order-ref.d.ts +45 -0
- package/dist/features/orders/utils/order-ref.js +58 -0
- package/dist/features/products/components/MakeOfferButton.d.ts +18 -1
- package/dist/features/products/components/MakeOfferButton.js +23 -1
- package/dist/features/products/components/ProductDetailPageView.d.ts +5 -0
- package/dist/features/products/components/ProductDetailPageView.js +3 -2
- package/dist/features/products/repository/products.repository.js +29 -2
- package/dist/features/seller/actions/offer-actions.js +32 -0
- package/dist/features/seller/components/QuickProductForm.js +15 -1
- package/dist/features/seller/components/SellerBidsView.js +3 -1
- package/dist/features/seller/components/SellerOffersView.js +2 -2
- package/dist/features/seller/components/SellerOrdersView.js +49 -6
- package/dist/features/seller/components/SellerProductsCards.js +23 -1
- package/dist/features/seller/components/SellerProductsView.js +27 -2
- package/dist/features/seller/hooks/useSellerListingData.d.ts +0 -1
- package/dist/features/seller/hooks/useSellerListingData.js +17 -19
- package/dist/features/shell/SectionForm.js +33 -2
- package/dist/features/tester/seed-data/_happy-path.d.ts +23 -0
- package/dist/features/tester/seed-data/_happy-path.js +710 -0
- package/dist/features/tester/seed-data/_money-flows.js +34 -23
- package/dist/features/tester/seed-data/authored/account-auth__profile-settings.js +22 -3
- package/dist/features/tester/seed-data/authored/addresses__address-filters.js +17 -12
- package/dist/features/tester/seed-data/authored/addresses__postal-lookup.js +7 -6
- package/dist/features/tester/seed-data/authored/addresses__postal-validation.js +10 -4
- package/dist/features/tester/seed-data/authored/addresses__state-picker.js +13 -8
- package/dist/features/tester/seed-data/authored/addresses__unban-request.js +49 -11
- package/dist/features/tester/seed-data/authored/admin__admin-detail-round-trips.js +10 -6
- package/dist/features/tester/seed-data/authored/admin__bans-and-trust.js +71 -32
- package/dist/features/tester/seed-data/authored/admin__blog-faqs.js +80 -31
- package/dist/features/tester/seed-data/authored/admin__bug-hunter-rewards.js +62 -25
- package/dist/features/tester/seed-data/authored/admin__bulk-actions.js +61 -31
- package/dist/features/tester/seed-data/authored/admin__bundles.js +84 -37
- package/dist/features/tester/seed-data/authored/admin__buyer-data-admin.js +90 -57
- package/dist/features/tester/seed-data/authored/admin__catalog-listings.js +38 -26
- package/dist/features/tester/seed-data/authored/admin__category-brand-authoring.js +47 -28
- package/dist/features/tester/seed-data/authored/admin__classifieds-digitalcodes-live.js +118 -31
- package/dist/features/tester/seed-data/authored/admin__content-deletes.js +30 -24
- package/dist/features/tester/seed-data/authored/admin__content-marketing.js +83 -46
- package/dist/features/tester/seed-data/authored/admin__coupons.js +8 -8
- package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +9 -9
- package/dist/features/tester/seed-data/authored/admin__firebase-function-effects.js +19 -4
- package/dist/features/tester/seed-data/authored/admin__media-watermark.js +77 -33
- package/dist/features/tester/seed-data/authored/admin__orders-fulfillment.js +5 -5
- package/dist/features/tester/seed-data/authored/admin__prize-draws-lotteries.js +29 -5
- package/dist/features/tester/seed-data/authored/admin__site-system.js +45 -23
- package/dist/features/tester/seed-data/authored/admin__uncovered-admin-pages.js +53 -28
- package/dist/features/tester/seed-data/authored/admin__users-trust.js +20 -20
- package/dist/features/tester/seed-data/authored/buying__bidding.js +19 -2
- package/dist/features/tester/seed-data/authored/buying__browsing-search.js +20 -5
- package/dist/features/tester/seed-data/authored/buying__buying-checkout.js +28 -10
- package/dist/features/tester/seed-data/authored/buying__cart.js +10 -3
- package/dist/features/tester/seed-data/authored/buying__image-tile-layout.js +0 -16
- package/dist/features/tester/seed-data/authored/buying__my-orders.js +27 -5
- package/dist/features/tester/seed-data/authored/buying__offers.js +22 -7
- package/dist/features/tester/seed-data/authored/buying__order-detail-actions.js +3 -3
- package/dist/features/tester/seed-data/authored/buying__product-detail.js +35 -4
- package/dist/features/tester/seed-data/authored/buying__return-request.js +19 -6
- package/dist/features/tester/seed-data/authored/buying__reviews-pagination.js +36 -18
- package/dist/features/tester/seed-data/authored/buying__reviews.js +16 -1
- package/dist/features/tester/seed-data/authored/buying__user-dashboard-navigation.js +2 -1
- package/dist/features/tester/seed-data/authored/buying__user-uncovered-pages.js +16 -1
- package/dist/features/tester/seed-data/authored/community-support__public-profile.js +3 -2
- package/dist/features/tester/seed-data/authored/community-support__support-tickets.js +4 -4
- package/dist/features/tester/seed-data/authored/content-discovery__blog.js +19 -2
- package/dist/features/tester/seed-data/authored/content-discovery__category-brand-relations.js +4 -4
- package/dist/features/tester/seed-data/authored/content-discovery__category-counts-and-rollup.js +5 -5
- package/dist/features/tester/seed-data/authored/content-discovery__coupons.js +41 -6
- package/dist/features/tester/seed-data/authored/content-discovery__event-detail-subroutes.js +63 -8
- package/dist/features/tester/seed-data/authored/content-discovery__event-participation.js +29 -29
- package/dist/features/tester/seed-data/authored/content-discovery__events.js +2 -2
- package/dist/features/tester/seed-data/authored/content-discovery__faq-help.js +23 -1
- package/dist/features/tester/seed-data/authored/content-discovery__notifications.js +6 -6
- package/dist/features/tester/seed-data/authored/content-discovery__search.js +1 -1
- package/dist/features/tester/seed-data/authored/content-discovery__store-reviews-aggregate.js +1 -1
- package/dist/features/tester/seed-data/authored/cta-layout__checkout-bottom-bar.js +31 -6
- package/dist/features/tester/seed-data/authored/cta-layout__dialog-footers.js +34 -10
- package/dist/features/tester/seed-data/authored/cta-layout__editor-action-bar.js +35 -8
- package/dist/features/tester/seed-data/authored/cta-layout__navbar-ctas.js +31 -9
- package/dist/features/tester/seed-data/authored/cta-layout__product-bottom-bar.js +29 -3
- package/dist/features/tester/seed-data/authored/design-ux__back-to-top-button.js +1 -1
- package/dist/features/tester/seed-data/authored/design-ux__carousel-arrow-bounds.js +10 -10
- package/dist/features/tester/seed-data/authored/design-ux__dashboard-layout.js +3 -3
- package/dist/features/tester/seed-data/authored/design-ux__footer-theme.js +2 -2
- package/dist/features/tester/seed-data/authored/design-ux__form-validation-errors.js +2 -2
- package/dist/features/tester/seed-data/authored/design-ux__general-design.js +4 -4
- package/dist/features/tester/seed-data/authored/design-ux__hand-mode-layout.js +1 -1
- package/dist/features/tester/seed-data/authored/design-ux__homepage-carousels.js +8 -8
- package/dist/features/tester/seed-data/authored/design-ux__status-badge-legibility.js +2 -2
- package/dist/features/tester/seed-data/authored/design-ux__sticky-cta-bar.js +2 -2
- package/dist/features/tester/seed-data/authored/page-wiring__data-loss.js +39 -16
- package/dist/features/tester/seed-data/authored/page-wiring__detail-pages.js +43 -8
- package/dist/features/tester/seed-data/authored/page-wiring__drawer-pages.js +40 -14
- package/dist/features/tester/seed-data/authored/page-wiring__reachability.js +31 -14
- package/dist/features/tester/seed-data/authored/public-pages__auth-error-pages.js +7 -6
- package/dist/features/tester/seed-data/authored/public-pages__bug-hunters.js +14 -5
- package/dist/features/tester/seed-data/authored/public-pages__core-listing-pages.js +3 -3
- package/dist/features/tester/seed-data/authored/public-pages__help-how-it-works.js +1 -1
- package/dist/features/tester/seed-data/authored/public-pages__help-scams-guides-subpages.js +4 -2
- package/dist/features/tester/seed-data/authored/public-pages__legal-policy-pages.js +3 -3
- package/dist/features/tester/seed-data/authored/public-pages__newly-wired-browse-indexes.js +5 -5
- package/dist/features/tester/seed-data/authored/public-pages__store-tabs.js +5 -5
- package/dist/features/tester/seed-data/authored/public-pages__stores-sellers-directories.js +3 -3
- package/dist/features/tester/seed-data/authored/search-and-nav__employee-permissions.js +45 -11
- package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +57 -17
- package/dist/features/tester/seed-data/authored/search-and-nav__settings-deep-links.js +36 -5
- package/dist/features/tester/seed-data/authored/search-and-nav__sidebar-search.js +29 -4
- package/dist/features/tester/seed-data/authored/selling__become-seller.js +23 -0
- package/dist/features/tester/seed-data/authored/selling__final-sale-authoring.js +14 -13
- package/dist/features/tester/seed-data/authored/selling__listing-a-product.js +14 -9
- package/dist/features/tester/seed-data/authored/selling__listing-edit-roundtrip.js +34 -7
- package/dist/features/tester/seed-data/authored/selling__listing-lifecycle.js +17 -7
- package/dist/features/tester/seed-data/authored/selling__listing-type-fields-roundtrip.js +9 -9
- package/dist/features/tester/seed-data/authored/selling__media-limits.js +9 -4
- package/dist/features/tester/seed-data/authored/selling__product-upload-details.js +3 -3
- package/dist/features/tester/seed-data/authored/selling__quick-add-minimum-details.js +3 -3
- package/dist/features/tester/seed-data/authored/selling__sectionised-forms.js +25 -1
- package/dist/features/tester/seed-data/authored/selling__seller-analytics-payouts.js +27 -6
- package/dist/features/tester/seed-data/authored/selling__seller-bids-bundles-filters.js +19 -1
- package/dist/features/tester/seed-data/authored/selling__seller-catalog-org.js +63 -22
- package/dist/features/tester/seed-data/authored/selling__seller-custom-brands.js +9 -5
- package/dist/features/tester/seed-data/authored/selling__seller-guide.js +7 -6
- package/dist/features/tester/seed-data/authored/selling__seller-listing-types.js +3 -2
- package/dist/features/tester/seed-data/authored/selling__seller-marketing-extras.js +18 -18
- package/dist/features/tester/seed-data/authored/selling__seller-ops-comms.js +13 -12
- package/dist/features/tester/seed-data/authored/selling__seller-orders-at-scale.js +19 -3
- package/dist/features/tester/seed-data/authored/selling__seller-orders.js +22 -4
- package/dist/features/tester/seed-data/authored/selling__seller-shipping-payouts-setup.js +20 -8
- package/dist/features/tester/seed-data/authored/selling__store-dashboard-navigation.js +4 -4
- package/dist/features/tester/seed-data/authored/selling__store-uncovered-pages.js +2 -2
- package/dist/features/tester/seed-data/authored/seo__canonical-and-host.js +5 -5
- package/dist/features/tester/seed-data/authored/seo__og-images.js +1 -1
- package/dist/features/tester/seed-data/authored/seo__page-metadata.js +7 -7
- package/dist/features/tester/seed-data/authored/seo__sitemap-and-robots.js +3 -3
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +123 -21
- package/dist/features/tester/utils/phases.d.ts +17 -0
- package/dist/features/tester/utils/phases.js +29 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/seo/json-ld.d.ts +23 -0
- package/dist/seo/json-ld.js +3 -2
- package/dist/server.d.ts +1 -0
- package/dist/server.js +2 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/PaginatedSelect.js +0 -0
- package/package.json +1 -1
|
@@ -80,11 +80,11 @@ export const authored = {
|
|
|
80
80
|
},
|
|
81
81
|
"checklist-admin-users-trust-roles-crud": {
|
|
82
82
|
roles: ["admin"],
|
|
83
|
-
startPage: "/admin/
|
|
83
|
+
startPage: "/admin/roles",
|
|
84
84
|
steps: [
|
|
85
85
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
86
|
-
"Open
|
|
87
|
-
"
|
|
86
|
+
"Open /admin/roles and read every role and its permissions.",
|
|
87
|
+
"Open /admin/permissions and confirm it redirects to /admin/roles?tab=permissions — it is a redirect-only shim, so the catalogue is a TAB rather than a page of its own. Check that tab is reachable from the sidebar under one name or the other.",
|
|
88
88
|
"Create a role named 'QA Role users-trust' with two permissions and save.",
|
|
89
89
|
"RELOAD and read its permissions.",
|
|
90
90
|
"Edit it to add a third, save, RELOAD, and check the first two are still there.",
|
|
@@ -135,7 +135,7 @@ export const authored = {
|
|
|
135
135
|
startPage: "/admin/addresses",
|
|
136
136
|
steps: [
|
|
137
137
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
138
|
-
"Open
|
|
138
|
+
"Open /admin/banned-addresses and read every column.",
|
|
139
139
|
"Check each row shows the address, who banned it, when, and why.",
|
|
140
140
|
"Read whether an unban request from the owner is visible on the row.",
|
|
141
141
|
"Open one and read the requester's full note before deciding anything.",
|
|
@@ -151,7 +151,7 @@ export const authored = {
|
|
|
151
151
|
startPage: "/admin/addresses",
|
|
152
152
|
steps: [
|
|
153
153
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
154
|
-
"Open
|
|
154
|
+
"Open /admin/address-clusters and read what a cluster row represents.",
|
|
155
155
|
"Check each row states how many accounts share the address and names them.",
|
|
156
156
|
"Open a cluster and read the accounts it groups.",
|
|
157
157
|
"Read whether the shared address itself is shown in full or masked.",
|
|
@@ -167,7 +167,7 @@ export const authored = {
|
|
|
167
167
|
startPage: "/admin/moderation",
|
|
168
168
|
steps: [
|
|
169
169
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
170
|
-
"Open
|
|
170
|
+
"Open /admin/moderation and read every row.",
|
|
171
171
|
"Check each row identifies what is being moderated and shows enough to judge it.",
|
|
172
172
|
"Open one item and read its full content — text, images, whatever was submitted.",
|
|
173
173
|
"Return to the list and check the same is reachable from the row itself.",
|
|
@@ -183,7 +183,7 @@ export const authored = {
|
|
|
183
183
|
startPage: "/admin/moderation",
|
|
184
184
|
steps: [
|
|
185
185
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
186
|
-
"Open
|
|
186
|
+
"Open /admin/moderation and open an item.",
|
|
187
187
|
"Read its content, then choose Reject.",
|
|
188
188
|
"Submit with the reason box empty and read what happens.",
|
|
189
189
|
"Type 'Too short' and submit, reading what happens.",
|
|
@@ -216,7 +216,7 @@ export const authored = {
|
|
|
216
216
|
startPage: "/admin/support-tickets",
|
|
217
217
|
steps: [
|
|
218
218
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
219
|
-
"Open
|
|
219
|
+
"Open /admin/support-tickets and read every column.",
|
|
220
220
|
"Read every status filter and select each, noting any that returns nothing.",
|
|
221
221
|
"Open a ticket and read the full message thread.",
|
|
222
222
|
"Reply to it and change its status in the same action.",
|
|
@@ -232,7 +232,7 @@ export const authored = {
|
|
|
232
232
|
startPage: "/admin/item-requests",
|
|
233
233
|
steps: [
|
|
234
234
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
235
|
-
"Open
|
|
235
|
+
"Open /admin/item-requests and read every row.",
|
|
236
236
|
"Check each row shows the requested item's title and description rather than only a requester.",
|
|
237
237
|
"Open one and read the full request before acting.",
|
|
238
238
|
"Read the actions offered and check a view exists alongside them.",
|
|
@@ -250,7 +250,7 @@ export const authored = {
|
|
|
250
250
|
startPage: "/user",
|
|
251
251
|
steps: [
|
|
252
252
|
"Sign in as rehan.sheikh@gmail.com / TempPass123!.",
|
|
253
|
-
"Open the item-request form
|
|
253
|
+
"Open /item-requests/new as the buyer — the public item-request form, not the admin queue at /admin/item-requests.",
|
|
254
254
|
"Submit it completely empty and read where the errors appear.",
|
|
255
255
|
"Type a title only and submit, reading what happens.",
|
|
256
256
|
"Type a one-word description and submit, reading what happens.",
|
|
@@ -267,7 +267,7 @@ export const authored = {
|
|
|
267
267
|
startPage: "/admin/reports",
|
|
268
268
|
steps: [
|
|
269
269
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
270
|
-
"Open
|
|
270
|
+
"Open /admin/reports and read every row.",
|
|
271
271
|
"Check each row names what was reported and by whom, and shows the reporter's stated detail.",
|
|
272
272
|
"Open one and read the full report before acting.",
|
|
273
273
|
"Read every status filter and select each, noting any that returns nothing.",
|
|
@@ -299,7 +299,7 @@ export const authored = {
|
|
|
299
299
|
startPage: "/admin/reports",
|
|
300
300
|
steps: [
|
|
301
301
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
302
|
-
"Open
|
|
302
|
+
"Open /admin/reports and open the report created by the buyer case.",
|
|
303
303
|
"Read its full detail, then choose Dismiss.",
|
|
304
304
|
"Submit with the reason empty and read what happens.",
|
|
305
305
|
"Type 'QA Dismissal users-trust — reviewed, no policy breach.' and submit.",
|
|
@@ -315,7 +315,7 @@ export const authored = {
|
|
|
315
315
|
startPage: "/admin/reports",
|
|
316
316
|
steps: [
|
|
317
317
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
318
|
-
"Open
|
|
318
|
+
"Open /admin/reports and open an open report.",
|
|
319
319
|
"Note the current date and time.",
|
|
320
320
|
"Close the report with a resolution note.",
|
|
321
321
|
"RELOAD and read the closed date shown.",
|
|
@@ -331,10 +331,10 @@ export const authored = {
|
|
|
331
331
|
startPage: "/admin/reports",
|
|
332
332
|
steps: [
|
|
333
333
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
334
|
-
"Open
|
|
334
|
+
"Open /admin/reports and read every status the status control offers.",
|
|
335
335
|
"Write the list down.",
|
|
336
336
|
"Select each in turn on a test report and confirm each is accepted.",
|
|
337
|
-
"Open
|
|
337
|
+
"Open /admin/reports and read every status filter chip.",
|
|
338
338
|
"Compare the chip list against the status list from the editor.",
|
|
339
339
|
"Note any chip naming a status the editor cannot set, or any status the editor sets that has no chip.",
|
|
340
340
|
],
|
|
@@ -347,7 +347,7 @@ export const authored = {
|
|
|
347
347
|
startPage: "/admin/catalogue-approvals",
|
|
348
348
|
steps: [
|
|
349
349
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
350
|
-
"Open
|
|
350
|
+
"Open /admin/catalogue-approvals and read every row.",
|
|
351
351
|
"Check each row shows the submitted item's photos, description and price.",
|
|
352
352
|
"Read every status filter and select each.",
|
|
353
353
|
"Open one submission and read everything the user submitted.",
|
|
@@ -362,7 +362,7 @@ export const authored = {
|
|
|
362
362
|
startPage: "/admin/catalogue-approvals",
|
|
363
363
|
steps: [
|
|
364
364
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
365
|
-
"Open
|
|
365
|
+
"Open /admin/catalogue-approvals and find a pending submission.",
|
|
366
366
|
"WITHOUT using Approve or Reject, find a way to open the submission in full.",
|
|
367
367
|
"Read every photo at full size and the complete description.",
|
|
368
368
|
"Read the price the submitter set and any linked marketplace listing.",
|
|
@@ -377,7 +377,7 @@ export const authored = {
|
|
|
377
377
|
startPage: "/admin/payment-methods",
|
|
378
378
|
steps: [
|
|
379
379
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
380
|
-
"Open
|
|
380
|
+
"Open /admin/payment-methods and read what a row represents.",
|
|
381
381
|
"Check each row states how many accounts share the instrument and names them.",
|
|
382
382
|
"Read how the payment identifier itself is displayed.",
|
|
383
383
|
"Search the page source for a full card or UPI identifier.",
|
|
@@ -522,7 +522,7 @@ export const authored = {
|
|
|
522
522
|
startPage: "/admin",
|
|
523
523
|
steps: [
|
|
524
524
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
525
|
-
"Open
|
|
525
|
+
"Open /admin/sections and open the section type picker.",
|
|
526
526
|
"Write down every type offered.",
|
|
527
527
|
"Compare the list against the section types the homepage can render.",
|
|
528
528
|
"Create one of each type not already present, saving after each.",
|
|
@@ -538,7 +538,7 @@ export const authored = {
|
|
|
538
538
|
startPage: "/admin/site",
|
|
539
539
|
steps: [
|
|
540
540
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
541
|
-
"Open
|
|
541
|
+
"Open /admin/analytics and find the threshold field.",
|
|
542
542
|
"Type abc into it and attempt to save.",
|
|
543
543
|
"Read where any error appears.",
|
|
544
544
|
"Type -5 and attempt to save, reading what happens.",
|
|
@@ -168,8 +168,25 @@ export const authored = {
|
|
|
168
168
|
"Read the bidder identity, amount and timestamp on every visible row.",
|
|
169
169
|
],
|
|
170
170
|
expectedBehaviour: "Bidder names are masked on the way out of the server, not hidden in the renderer. The masking helper for bids once returned its input unchanged while being named as though it masked — every bidder's real name was in the public payload and nothing displayed it, so the leak was invisible from the screen. Displaying the masked name is what makes that checkable by eye.",
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
/*
|
|
172
|
+
* 🛑 THE FORBIDDEN NAMES WERE FICTIONAL, SO THE PII CHECK PASSED VACUOUSLY.
|
|
173
|
+
*
|
|
174
|
+
* This asserted that 'Meera Bey', 'Rohit Collector' or 'Ananya Collector'
|
|
175
|
+
* must not appear. Those three strings occur ZERO times in the seed: the
|
|
176
|
+
* personas' displayName values are "Mock User 11", "Mock User 14" and
|
|
177
|
+
* "Mock User 9". So the assertion could never fail — it would report a
|
|
178
|
+
* clean PII check whether masking worked or not, which is the one outcome
|
|
179
|
+
* worse than no check at all.
|
|
180
|
+
*
|
|
181
|
+
* The masked shape was wrong for the same reason: 'M*** B***' is the mask
|
|
182
|
+
* of "Meera Bey". maskName splits on whitespace and keeps each word's first
|
|
183
|
+
* character, so "Mock User 11" becomes "M*** U*** 11***".
|
|
184
|
+
*
|
|
185
|
+
* Bidder uids are right (meera-bey, rohit-collector, ananya-collector all
|
|
186
|
+
* bid on this auction) — only the names they resolve to were invented.
|
|
187
|
+
*/
|
|
188
|
+
expectedUiState: "Each row reads in the shape '₹3,199.00 · M*** U*** 11*** · 4 Sept, 17:06'. The name is genuinely masked — every word reduced to its first character plus asterisks — and is not a full readable name, and not a placeholder like 'Bidder'. The timestamp carries both a date and a clock time, not a date alone.",
|
|
189
|
+
endResult: "The same masked names and timestamps appear after reload. An unmasked display name — 'Mock User 9', 'Mock User 11' or 'Mock User 14', the three seeded bidders on this auction — anywhere in these rows is a PII leak and fails the case outright.",
|
|
173
190
|
},
|
|
174
191
|
"checklist-buying-bidding-bid-increment-live-tier-change": {
|
|
175
192
|
roles: ["buyer"],
|
|
@@ -621,14 +621,29 @@ export const authored = {
|
|
|
621
621
|
"Open /auctions.",
|
|
622
622
|
"Click the 'Ended' tab.",
|
|
623
623
|
"Scan the grid for 'Beyblade Burst B-128 Spriggan Requiem (Ended — Bought Out)' (auction-beyblade-burst-spriggan-requiem-bought-out).",
|
|
624
|
-
|
|
624
|
+
/*
|
|
625
|
+
* 🛑 'Available', not 'Live' — and on the next page 'Ended', not 'Closed'.
|
|
626
|
+
*
|
|
627
|
+
* `availabilityTabsFor` builds exactly three tabs and only the MIDDLE one
|
|
628
|
+
* varies: its label comes from HIDE_DEFAULT_NOUN, which maps every
|
|
629
|
+
* hideDefault onto "Sold" or "Ended" and nothing else. Prize-draw's
|
|
630
|
+
* `hideDefault: "closed"` maps to "Ended", so /prize-draws reads
|
|
631
|
+
* Available / Ended / All.
|
|
632
|
+
*
|
|
633
|
+
* The first tab is ALWAYS 'Available'. This case named it 'Live' on
|
|
634
|
+
* /auctions and 'Open' on /prize-draws, and called the prize-draw middle
|
|
635
|
+
* tab 'Closed' — three controls that render under different names, so the
|
|
636
|
+
* tester would hunt, fail to find them, and answer "could not test" on a
|
|
637
|
+
* feature that works.
|
|
638
|
+
*/
|
|
639
|
+
"Click the 'Available' tab.",
|
|
625
640
|
"Open /prize-draws.",
|
|
626
|
-
"Click the '
|
|
641
|
+
"Click the 'Ended' tab.",
|
|
627
642
|
"Scan the grid for 'Metal Fight Mystery Draw — Ended (Revealed)' (prizedraw-beyblade-metal-closed-revealed).",
|
|
628
|
-
"Click the '
|
|
643
|
+
"Click the 'Available' tab.",
|
|
629
644
|
],
|
|
630
|
-
expectedBehaviour: "The 'Available'
|
|
631
|
-
expectedUiState: "'Beyblade X BX-34 Dran Buster (Sold Out)' appears on the 'Sold & Ended' tab and is absent on 'Available'. 'Beyblade Burst B-128 Spriggan Requiem (Ended — Bought Out)' appears on 'Ended' and is absent on '
|
|
645
|
+
expectedBehaviour: "The 'Available' tab hides sold-out, ended and closed items on every listing page; the middle tab reveals them. Only the middle label varies by listing type — 'Sold & Ended' on /products, 'Ended' on /auctions and on /prize-draws.",
|
|
646
|
+
expectedUiState: "'Beyblade X BX-34 Dran Buster (Sold Out)' appears on the 'Sold & Ended' tab and is absent on 'Available'. 'Beyblade Burst B-128 Spriggan Requiem (Ended — Bought Out)' appears on /auctions' 'Ended' tab and is absent on 'Available'. 'Metal Fight Mystery Draw — Ended (Revealed)' appears on /prize-draws' 'Ended' tab and is absent on 'Available'. No page offers a tab labelled 'Live', 'Open' or 'Closed'.",
|
|
632
647
|
endResult: "Nothing is persisted. Tab state is URL state only.",
|
|
633
648
|
},
|
|
634
649
|
"checklist-buying-browsing-search-sort-options-per-listing-type": {
|
|
@@ -337,14 +337,30 @@ export const authored = {
|
|
|
337
337
|
roles: ["buyer"],
|
|
338
338
|
startPage: "/checkout",
|
|
339
339
|
steps: [
|
|
340
|
-
|
|
340
|
+
/*
|
|
341
|
+
* 🛑 THE BUYER CHOOSES THIS AT CHECKOUT — it is not an admin setting.
|
|
342
|
+
*
|
|
343
|
+
* This step said "Sign in as admin and set Site Settings → Checkout →
|
|
344
|
+
* Out-of-stock policy". There is no such setting: `outOfStockPolicy` is a
|
|
345
|
+
* POLICY_SECTIONS field rendered by CheckoutRouteClient and passed
|
|
346
|
+
* straight into createCheckoutOrder. It appears nowhere in the admin
|
|
347
|
+
* feature. A tester would have hunted through Site Settings, not found
|
|
348
|
+
* it, and answered "could not test".
|
|
349
|
+
*
|
|
350
|
+
* The option labels were wrong too — 'Cancel whole order' is the app's
|
|
351
|
+
* "Cancel my whole order", and the sibling case's 'Skip unavailable
|
|
352
|
+
* items' is actually "Ship what's available and refund the rest", which
|
|
353
|
+
* shares no words with what the case asked for.
|
|
354
|
+
*/
|
|
341
355
|
"Sign in as rehan.sheikh@gmail.com / TempPass123!.",
|
|
342
|
-
"Add product-beyblade-burst-valkyrie (₹999, stock 10) and product-beyblade-original-dranzer-s (₹
|
|
343
|
-
"
|
|
356
|
+
"Add product-beyblade-burst-valkyrie (₹999, stock 10) and product-beyblade-original-dranzer-s (₹1,499) to the cart.",
|
|
357
|
+
"Open /checkout and advance to the payment step.",
|
|
358
|
+
"Under 'If an item goes out of stock', select 'Cancel my whole order'.",
|
|
359
|
+
"Before submitting, have another session reduce product-beyblade-burst-valkyrie's stock to 0.",
|
|
344
360
|
"Submit the checkout.",
|
|
345
361
|
],
|
|
346
|
-
inputs: { policy: "Cancel whole order", goesOutOfStock: "product-beyblade-burst-valkyrie" },
|
|
347
|
-
expectedBehaviour: "With the
|
|
362
|
+
inputs: { policy: "Cancel my whole order", goesOutOfStock: "product-beyblade-burst-valkyrie" },
|
|
363
|
+
expectedBehaviour: "With the cancel-whole-order policy, if any item in the batch goes out of stock mid-checkout, the entire checkout is rejected. No order is created and the buyer receives an error.",
|
|
348
364
|
expectedUiState: "After submitting, an error message is shown indicating that an item went out of stock and the entire order was cancelled. No order confirmation page is shown.",
|
|
349
365
|
expectedData: { ordersCreated: 0 },
|
|
350
366
|
endResult: "After reloading /cart, both items are still present in the cart (or the buyer is able to restart the checkout). No order record exists for this attempt.",
|
|
@@ -353,14 +369,16 @@ export const authored = {
|
|
|
353
369
|
roles: ["buyer"],
|
|
354
370
|
startPage: "/checkout",
|
|
355
371
|
steps: [
|
|
356
|
-
|
|
372
|
+
/* Buyer-chosen at checkout, not an admin setting — see the sibling case. */
|
|
357
373
|
"Sign in as rehan.sheikh@gmail.com / TempPass123!.",
|
|
358
|
-
"Add product-beyblade-burst-valkyrie (₹999, stock 10) and product-beyblade-original-dranzer-s (₹
|
|
359
|
-
"
|
|
374
|
+
"Add product-beyblade-burst-valkyrie (₹999, stock 10) and product-beyblade-original-dranzer-s (₹1,499) to the cart.",
|
|
375
|
+
"Open /checkout and advance to the payment step.",
|
|
376
|
+
"Under 'If an item goes out of stock', select 'Ship what's available and refund the rest'.",
|
|
377
|
+
"Before submitting, have another session reduce product-beyblade-original-dranzer-s's stock to 0.",
|
|
360
378
|
"Submit the checkout.",
|
|
361
379
|
],
|
|
362
|
-
inputs: { policy: "
|
|
363
|
-
expectedBehaviour: "With the '
|
|
380
|
+
inputs: { policy: "Ship what's available and refund the rest", goesOutOfStock: "product-beyblade-original-dranzer-s" },
|
|
381
|
+
expectedBehaviour: "With the ship-what's-available policy, the out-of-stock item is dropped and an order is placed for only the still-available item(s). The buyer is informed which item was skipped.",
|
|
364
382
|
expectedUiState: "After submitting, the order confirmation page shows only product-beyblade-burst-valkyrie (₹999). A notice is shown indicating that product-beyblade-original-dranzer-s was unavailable and was removed from the order.",
|
|
365
383
|
expectedData: { orderLineCount: 1 },
|
|
366
384
|
endResult: "After reloading the order detail page, only product-beyblade-burst-valkyrie is listed in the order. product-beyblade-original-dranzer-s is not included.",
|
|
@@ -601,7 +601,7 @@ export const authored = {
|
|
|
601
601
|
startPage: "/store/bundles",
|
|
602
602
|
steps: [
|
|
603
603
|
"Sign in as tyson@beybladearena.in / TempPass123!.",
|
|
604
|
-
"Open
|
|
604
|
+
"Open /store/bundles and start creating one.",
|
|
605
605
|
"Add a member from this store and one from a different store.",
|
|
606
606
|
"Save and read the message.",
|
|
607
607
|
"Check the message names the offending member or store.",
|
|
@@ -729,7 +729,7 @@ export const authored = {
|
|
|
729
729
|
"Open /cart and read the Won Auctions tab.",
|
|
730
730
|
"Check the line is gone.",
|
|
731
731
|
"Open /user/bids and read that bid's status.",
|
|
732
|
-
"Open
|
|
732
|
+
"Open /user/notifications and read the forfeiture entry.",
|
|
733
733
|
"Check the Cart tab's checkout is now enabled again.",
|
|
734
734
|
],
|
|
735
735
|
expectedBehaviour: "An unpaid win past its deadline is forfeited, the locked line cleared and the buyer notified. Clearing the line is what unblocks the rest of the cart — a leftover locked line keeps the auction lane non-empty and that lane outranks the others, so the buyer's whole cart stays blocked indefinitely.",
|
|
@@ -945,7 +945,14 @@ export const authored = {
|
|
|
945
945
|
startPage: "/cart",
|
|
946
946
|
steps: [
|
|
947
947
|
"Sign in as rehan.sheikh@gmail.com / TempPass123! with items from TWO sellers.",
|
|
948
|
-
|
|
948
|
+
/*
|
|
949
|
+
* 'WhatsApp updates' — the label StoreAddonsPicker actually renders,
|
|
950
|
+
* under an 'Add-ons' heading on each seller's card. This said 'WhatsApp
|
|
951
|
+
* order updates', which appears nowhere; CartPriceBreakdown's matching
|
|
952
|
+
* FEE LINE reads 'WhatsApp updates' too, so neither surface uses the
|
|
953
|
+
* longer form.
|
|
954
|
+
*/
|
|
955
|
+
"Open /cart and tick 'WhatsApp updates' under 'Add-ons' on ONE seller's card only.",
|
|
949
956
|
"Read that seller's fee lines and the aggregate breakdown.",
|
|
950
957
|
"Check the fee is charged once at ₹10.00, not ₹20.00.",
|
|
951
958
|
"Check the other seller's card shows no such fee.",
|
|
@@ -87,22 +87,6 @@ export const authored = {
|
|
|
87
87
|
expectedUiState: "Every tile shows its image above its caption, all at the same width, at both viewport sizes. An image sitting beside its caption and squeezed narrow is the row-direction failure.",
|
|
88
88
|
endResult: "Read-only; restore the window width afterwards.",
|
|
89
89
|
},
|
|
90
|
-
"checklist-buying-image-tile-layout-concern-card-icon-above-label": {
|
|
91
|
-
roles: ["guest"],
|
|
92
|
-
startPage: "/",
|
|
93
|
-
steps: [
|
|
94
|
-
"Open / in a private window at 1280 pixels wide.",
|
|
95
|
-
"Find the concern or trust cards and look at each one.",
|
|
96
|
-
"Check each card's icon sits above its label rather than beside it.",
|
|
97
|
-
"Compare the icon's size against the card's own height.",
|
|
98
|
-
"Resize to 390 pixels and check the arrangement holds.",
|
|
99
|
-
"Switch to dark mode and check the icons are still visible.",
|
|
100
|
-
],
|
|
101
|
-
inputs: { desktopWidth: 1280, mobileWidth: 390 },
|
|
102
|
-
expectedBehaviour: "These cards carry an explicitly-sized icon box, which is what kept them from collapsing entirely when the wrapper defect hit — but an explicit size does not fix the direction, so they still laid the icon out beside the label. Sizing and direction are two separate failures and this card had only one of them.",
|
|
103
|
-
expectedUiState: "Each card shows its icon above its label at both widths, with the icon proportionate to the card. An icon beside its label, or one at the platform font's fallback size, are different failures and should be reported as such.",
|
|
104
|
-
endResult: "Read-only; return to light mode and restore the width.",
|
|
105
|
-
},
|
|
106
90
|
"checklist-buying-image-tile-layout-media-picker-existing-grid": {
|
|
107
91
|
roles: ["seller"],
|
|
108
92
|
startPage: "/store/products/new",
|
|
@@ -242,11 +242,33 @@ export const authored = {
|
|
|
242
242
|
roles: ["buyer"],
|
|
243
243
|
startPage: "/user/orders",
|
|
244
244
|
steps: [
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
245
|
+
/*
|
|
246
|
+
* 🛑 THE ACCOUNT MUST BE THE HARNESS MAILBOX, AND NO SEEDED PERSONA IS.
|
|
247
|
+
*
|
|
248
|
+
* This step used to read "an account whose inbox you can open", which is
|
|
249
|
+
* not a literal value and quietly hid a real constraint. Two mechanisms
|
|
250
|
+
* can settle an email case, and BOTH key on TESTER_EMAIL_ID:
|
|
251
|
+
*
|
|
252
|
+
* - check-inbox.mjs reads that mailbox over IMAP
|
|
253
|
+
* - the emailEvents recorder writes a row ONLY when the recipient
|
|
254
|
+
* equals TESTER_EMAIL_ID (or EMAIL_RECORDER_ALL is set)
|
|
255
|
+
*
|
|
256
|
+
* Every seeded persona uses a real-looking address the harness does not
|
|
257
|
+
* own, so an order placed as rehan produces nothing either instrument can
|
|
258
|
+
* see. Gmail plus-addressing is the way in: a fresh signup at
|
|
259
|
+
* <harness-mailbox>+run3@gmail.com is delivered to the same inbox.
|
|
260
|
+
*
|
|
261
|
+
* Capture the timestamp BEFORE placing the order. The mailbox is shared
|
|
262
|
+
* across every case in every run, so "newest matching message" will
|
|
263
|
+
* happily return one an earlier case left behind — which reads as a pass
|
|
264
|
+
* for an email this action never sent.
|
|
265
|
+
*/
|
|
266
|
+
"Register a new account at /auth/register using the harness mailbox with a run-stamped plus-address (the value of TESTER_EMAIL_ID in tester/.env, e.g. name+run3@gmail.com), and confirm order emails are enabled in its notification settings.",
|
|
267
|
+
"Run `node -e \"console.log(Date.now())\"` and keep that number.",
|
|
268
|
+
"Place an order as that account.",
|
|
269
|
+
"Run `node tester/scripts/check-inbox.mjs --since <that number> --subject \"order\"` and read the exit code: 0 the mail arrived, 1 it did not, 2 the mailbox could not be opened.",
|
|
270
|
+
"Read the message's From name, its subject and its body.",
|
|
271
|
+
"Have the seller mark the order shipped, capture a fresh timestamp, and run check-inbox.mjs again with --subject \"shipped\".",
|
|
250
272
|
"Click a link inside each email and read where it lands.",
|
|
251
273
|
"Compare each email's figures against the order itself.",
|
|
252
274
|
],
|
|
@@ -52,10 +52,10 @@ export const authored = {
|
|
|
52
52
|
"Read the row — product, offered amount, listed price, status and round.",
|
|
53
53
|
"Open the row action menu and read every action offered.",
|
|
54
54
|
"Use Counter, then cancel out of the form without submitting.",
|
|
55
|
-
"Use
|
|
55
|
+
"Use Reject on a DIFFERENT pending offer and read what happens.",
|
|
56
56
|
"Reload and read that offer's status.",
|
|
57
57
|
],
|
|
58
|
-
expectedBehaviour: "The seller's list shows incoming offers with the context needed to decide, and Accept,
|
|
58
|
+
expectedBehaviour: "The seller's list shows incoming offers with the context needed to decide, and Accept, Reject and Counter all act. The store keeps sole authority over its own pricing — this is the surface where that authority lives.",
|
|
59
59
|
expectedUiState: "Rows show product, amounts, status and round. All three actions are present and act. The declined offer reads as declined after the reload.",
|
|
60
60
|
endResult: "One offer is declined; QA Offer make-offer is untouched.",
|
|
61
61
|
},
|
|
@@ -82,7 +82,7 @@ export const authored = {
|
|
|
82
82
|
steps: [
|
|
83
83
|
"Sign in as tyson@beybladearena.in / TempPass123!.",
|
|
84
84
|
"Open /store/offers and find a pending offer.",
|
|
85
|
-
"WITHOUT using Accept,
|
|
85
|
+
"WITHOUT using Accept, Reject or Counter, find a way to open its details.",
|
|
86
86
|
"Read the buyer's note, the listed price, the offered amount and the round.",
|
|
87
87
|
"Read any earlier rounds in the same negotiation.",
|
|
88
88
|
"Return to the list and check the same is reachable from the row.",
|
|
@@ -243,12 +243,12 @@ export const authored = {
|
|
|
243
243
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
244
244
|
"Open the admin offers surface and open a pending offer's row menu.",
|
|
245
245
|
"Read every action offered and write the list down.",
|
|
246
|
-
"Check for Accept, Counter or
|
|
246
|
+
"Check for Accept, Counter or Reject.",
|
|
247
247
|
"Select several rows and read any bulk action bar that appears.",
|
|
248
248
|
"Read whether a bulk cancel is offered.",
|
|
249
249
|
],
|
|
250
250
|
expectedBehaviour: "Admin is a coordinator, not a participant: only View and Cancel. The store keeps sole authority over its own pricing. There is deliberately no bulk cancel — one shared reason across a heterogeneous selection is worse audit data than none, and a registry-backed control that reads as working while doing nothing is worse than an absent one.",
|
|
251
|
-
expectedUiState: "The menu offers View and Cancel only. No Accept, Counter or
|
|
251
|
+
expectedUiState: "The menu offers View and Cancel only. No Accept, Counter or Reject. No bulk cancel appears — and if one does, it must actually act rather than only clearing the selection.",
|
|
252
252
|
expectedData: { adminActions: 2 },
|
|
253
253
|
endResult: "Read-only; act on nothing.",
|
|
254
254
|
},
|
|
@@ -259,11 +259,26 @@ export const authored = {
|
|
|
259
259
|
"Sign in as tyson@beybladearena.in / TempPass123!.",
|
|
260
260
|
"Open /store/offers and open a pending offer's row menu.",
|
|
261
261
|
"Read every action offered.",
|
|
262
|
-
"Check Accept, Counter and
|
|
262
|
+
"Check Accept, Counter and Reject are all present.",
|
|
263
263
|
"Use Accept on one and reload.",
|
|
264
264
|
"Read the offer's status and check the buyer's cart gains a line for it.",
|
|
265
265
|
],
|
|
266
|
-
expectedBehaviour:
|
|
266
|
+
expectedBehaviour:
|
|
267
|
+
/*
|
|
268
|
+
* 'Reject', not 'Decline'. SellerOffersView renders its row menu from
|
|
269
|
+
* ACTIONS.STORE["accept-offer" | "counter-offer" | "reject-offer"], whose
|
|
270
|
+
* labels are Accept / Counter / Reject. Nothing in the menu says Decline.
|
|
271
|
+
*
|
|
272
|
+
* The confusion is real and worth naming: the offer STATUS is `declined`,
|
|
273
|
+
* and this project's own docs describe the seller as able to
|
|
274
|
+
* "accept / counter / decline". Both are true of the outcome — but a case
|
|
275
|
+
* tells a tester which BUTTON to click, and that button says Reject.
|
|
276
|
+
*
|
|
277
|
+
* Note SELLER_ROW_ACTIONS.offers ([VIEW, APPROVE, REJECT]) is NOT what
|
|
278
|
+
* this view uses, so reading the action-defs preset would give a third
|
|
279
|
+
* answer again.
|
|
280
|
+
*/
|
|
281
|
+
"Adding an admin surface must not have removed the store's own actions. The seller retains Accept, Counter and Reject — an admin coordinating a dispute is a different capability from the seller deciding their own price.",
|
|
267
282
|
expectedUiState: "All three actions are present and Accept works. The accepted offer reads accepted and produces a cart line in the buyer's offer lane.",
|
|
268
283
|
endResult: "One offer is accepted.",
|
|
269
284
|
},
|
|
@@ -33,7 +33,7 @@ export const authored = {
|
|
|
33
33
|
"Read what the browser does with the response.",
|
|
34
34
|
],
|
|
35
35
|
expectedBehaviour: "The invoice is generated on demand and streamed by a route that checks the order belongs to the caller. It is not a stored file and has no public URL.",
|
|
36
|
-
expectedUiState: "
|
|
36
|
+
expectedUiState: "The invoice opens as a readable print view with a Print / Save as PDF control — it is not a JSON blob and not an error page. It does NOT download a file, and that is by design. Check the MONEY: every fee in the total must have its own row, so Subtotal + Shipping + each fee equals the stated Total exactly.",
|
|
37
37
|
expectedData: { invoiceDownloaded: true },
|
|
38
38
|
endResult: "The order is unchanged by downloading its invoice; the row still shows the same status after a reload.",
|
|
39
39
|
},
|
|
@@ -106,12 +106,12 @@ export const authored = {
|
|
|
106
106
|
startPage: "/user/orders",
|
|
107
107
|
steps: [
|
|
108
108
|
"Sign in as rehan.sheikh@gmail.com / TempPass123! — this persona owns the seeded SHIPPED order.",
|
|
109
|
-
"Open /user/orders and open order-1-
|
|
109
|
+
"Open /user/orders and open order-1-20251122-481j4x.",
|
|
110
110
|
"Use the Track action.",
|
|
111
111
|
"Read every step on the timeline and note which carry a date and which do not.",
|
|
112
112
|
"Compare the dates shown against the order's own placed and shipped dates.",
|
|
113
113
|
],
|
|
114
|
-
inputs: { orderId: "order-1-
|
|
114
|
+
inputs: { orderId: "order-1-20251122-481j4x" },
|
|
115
115
|
expectedBehaviour: "Each timeline step shows the date actually recorded for it. A step with no recorded date renders an em-dash rather than a guess — an invented or estimated date is worse than a blank, because it cannot be told apart from a real one.",
|
|
116
116
|
expectedUiState: "The placed and shipped steps carry dates matching the order. Steps the order has not reached show no date rather than today's.",
|
|
117
117
|
expectedData: { fabricatedDatesShown: false },
|
|
@@ -126,7 +126,22 @@ export const authored = {
|
|
|
126
126
|
],
|
|
127
127
|
inputs: { productId: "digitalcode-beyblade-x-app-starter-pack", price: 199, codesAvailable: 25, paymentMethod: "Cash on Delivery" },
|
|
128
128
|
expectedBehaviour: "This fixture is auto-claim, so the code is allocated and delivered as soon as the order is confirmed, with no seller action in between. The pool's remaining count drops by one. The listing advertises 25 codes on the product document, but the codes themselves live in a subcollection the seed does not write — so the pool must be stocked first from the seller's Digital Content pool manager on /store/products, or the purchase completes and delivers nothing, which is the exact defect this case exists to catch.",
|
|
129
|
-
|
|
129
|
+
/*
|
|
130
|
+
* 🛑 THE FORBIDDEN STATES DID NOT EXIST, SO THE ASSERTION COULD NOT FAIL.
|
|
131
|
+
*
|
|
132
|
+
* This forbade 'Pending delivery' and 'Waiting for seller'. Neither string
|
|
133
|
+
* is anywhere in the source: CodeRevealPanel renders 'Your Digital Code',
|
|
134
|
+
* 'Your Digital Content', 'Your download', 'Copied!' and one error —
|
|
135
|
+
* 'Could not retrieve your code. Please try again.'
|
|
136
|
+
*
|
|
137
|
+
* That matters more here than on most pages. Root Cause #103 is exactly
|
|
138
|
+
* this failure: the pool had no writer, so every purchase logged "code pool
|
|
139
|
+
* exhausted", returned silently, completed the order normally, and left the
|
|
140
|
+
* reveal answering 404. The real symptom is an ABSENT or ERRORING panel —
|
|
141
|
+
* and forbidding two states the app never renders meant this case would
|
|
142
|
+
* have passed straight through it.
|
|
143
|
+
*/
|
|
144
|
+
expectedUiState: "The order page shows a digital-code panel headed 'Your Digital Code' (or 'Your Digital Content') containing an actual code string that can be selected and copied. The panel is present at all — an absent panel, a 404 from the reveal request, or the text 'Could not retrieve your code. Please try again.' each mean the delivery never fired, which for an auto-claim listing is the defect this case exists to catch.",
|
|
130
145
|
expectedData: { codeDelivered: true },
|
|
131
146
|
endResult: "Reloading the order still shows the same delivered code. A code that appears once and is blank after reload was never persisted against the order.",
|
|
132
147
|
},
|
|
@@ -183,7 +198,16 @@ export const authored = {
|
|
|
183
198
|
"Look at the gallery thumbnail strip.",
|
|
184
199
|
],
|
|
185
200
|
expectedBehaviour: "A live listing renders its species-specific fields — species, breed, sex, age and the jurisdiction restrictions — which no other listing type carries, and offers a cart path once those restrictions are satisfied.",
|
|
186
|
-
expectedUiState:
|
|
201
|
+
expectedUiState:
|
|
202
|
+
/*
|
|
203
|
+
* Title and price taken from the seed, not from the deleted sandbox.
|
|
204
|
+
* This read 'Test Live Item — Golden Retriever Puppy' at '₹1,500.00' —
|
|
205
|
+
* a fixture from the tester-sandbox catalogue that was removed with
|
|
206
|
+
* testerSandboxRefresh. The real row is live-golden-retriever-puppy at
|
|
207
|
+
* ₹25,000. The guest-gate half of this expectation was migrated
|
|
208
|
+
* correctly; only the literals were left pointing at the old catalogue.
|
|
209
|
+
*/
|
|
210
|
+
"Heading 'Golden Retriever Puppy — 6 Months, Vaccinated'. A species line in the shape 'Dog (Golden Retriever) · male · 6mo'. BEFORE: the price read '₹25,000.00'; AFTER it reads 'Sign in to see price' and the digits 25,000 appear nowhere, and the 'Handling:' fee on the transport line is absent too. Delivery restrictions are stated rather than blank. The thumbnail strip carries a 'View video' entry alongside 'View image 1'. An 'Add to Cart' button is present.",
|
|
187
211
|
endResult: "Nothing persists — read-only for a guest.",
|
|
188
212
|
},
|
|
189
213
|
"checklist-buying-product-detail-live-item-video-mandatory": {
|
|
@@ -221,7 +245,14 @@ export const authored = {
|
|
|
221
245
|
"Read the note beside the 'Reserve Now' button.",
|
|
222
246
|
],
|
|
223
247
|
expectedBehaviour: "A pre-order shows an estimated delivery date and takes a deposit rather than the full price, which is what distinguishes it from a standard listing that happens to be out of stock.",
|
|
224
|
-
expectedUiState:
|
|
248
|
+
expectedUiState:
|
|
249
|
+
/*
|
|
250
|
+
* Same sandbox leftover as the live-item case above. The real row is
|
|
251
|
+
* preorder-beyblade-x-bx-08-wave: ₹799 at preOrderDepositPercent 25, so
|
|
252
|
+
* the deposit is ₹199.75 — figures a tester can check against the seed
|
|
253
|
+
* rather than against a fixture that no longer exists.
|
|
254
|
+
*/
|
|
255
|
+
"Heading 'Beyblade X BX-08 Booster — Next Wave'. BEFORE: the price read '₹799.00' with a 'Reserve with ₹199.75' note; AFTER the price reads 'Sign in to see price', the deposit note is absent entirely, and neither 799 nor 199.75 appears anywhere on the page. An 'Estimated delivery:' label with an actual date beside it, not an empty value or the word 'undefined'. A 'Reserve Now' button is still present. Status badge 'In Production'.",
|
|
225
256
|
endResult: "Nothing persists — read-only for a guest.",
|
|
226
257
|
},
|
|
227
258
|
"checklist-buying-product-detail-prizedraw-buy-reveal": {
|
|
@@ -261,7 +292,7 @@ export const authored = {
|
|
|
261
292
|
groupTitle: "QA Set valkyrie-lineage",
|
|
262
293
|
},
|
|
263
294
|
expectedBehaviour: "The group panel appears on the parent and on the child, because membership is symmetric — a child knows its groupId and the parent knows its child slugs. A panel that renders only on the parent means the children's side of the link was never written. The group is BUILT by this case rather than read from the seed: no seeded product carries groupId, isGroupParent or groupChildSlugs, so there is no fixture to read.",
|
|
264
|
-
expectedUiState: "The panel is present on both pages. Its expand control renders as a real triangle or chevron glyph, not a literal character like '▸' rendered at font-fallback size and not a missing box. Expanded, it lists 'Beyblade Burst B-01 Valkyrie' and 'Beyblade Burst B-
|
|
295
|
+
expectedUiState: "The panel is present on both pages. Its expand control renders as a real triangle or chevron glyph, not a literal character like '▸' rendered at font-fallback size and not a missing box. Expanded, it lists 'Beyblade Burst B-01 Valkyrie' and 'Beyblade Burst B-59 Regalia Genesis' with image tiles. 'View whole group' opens a modal or drawer showing both members.",
|
|
265
296
|
expectedData: { groupMemberCount: 2 },
|
|
266
297
|
endResult: "Clear the group settings on both listings afterwards so the seeded catalogue is left as it was. A panel that survives on the parent but never appeared on the child is the failure.",
|
|
267
298
|
},
|
|
@@ -47,14 +47,27 @@ export const authored = {
|
|
|
47
47
|
startPage: "/user/orders",
|
|
48
48
|
steps: [
|
|
49
49
|
"Sign in as rehan.sheikh@gmail.com / TempPass123!.",
|
|
50
|
-
"Open /user/orders and
|
|
50
|
+
"Open /user/orders and open any delivered order — every seeded listing is final sale, because ProductDocument.finalSale is ABSENT on all of them and absent means true.",
|
|
51
51
|
"Confirm the order or its item shows the final-sale term.",
|
|
52
52
|
"Open the return control and read every reason it offers.",
|
|
53
|
-
|
|
53
|
+
/*
|
|
54
|
+
* 🛑 THE RENDERED LABEL, NOT THE ENUM VALUE OR A PARAPHRASE.
|
|
55
|
+
*
|
|
56
|
+
* These steps said "the not-received reason" and "the change-of-mind
|
|
57
|
+
* reason". The stored codes really are `not_received` and `changed_mind`
|
|
58
|
+
* — but RETURN_REASON_LABEL renders them as 'It never arrived' and
|
|
59
|
+
* 'I changed my mind', and neither paraphrase appears on screen.
|
|
60
|
+
*
|
|
61
|
+
* A tester scanning a select for "not received" does not find it. Same
|
|
62
|
+
* shape as the Decline/Reject button on buying/offers: the code value and
|
|
63
|
+
* the label are two different registers, and a step names the one the
|
|
64
|
+
* user clicks.
|
|
65
|
+
*/
|
|
66
|
+
"Select 'It never arrived'.",
|
|
54
67
|
"Type 'QA Return not-received — the parcel never arrived.' and submit.",
|
|
55
68
|
"RELOAD the order and read its status.",
|
|
56
69
|
],
|
|
57
|
-
inputs: { reason: "
|
|
70
|
+
inputs: { reason: "It never arrived", note: "QA Return not-received — the parcel never arrived." },
|
|
58
71
|
expectedBehaviour: "Final sale does not override non-delivery. It is a statement about changing your mind, not about whether the seller has to deliver — so a not-received claim must be accepted on a final-sale item, and refusing it converts a delivery failure into a term the buyer never agreed to.",
|
|
59
72
|
expectedUiState: "The not-received reason is offered and accepted despite the final-sale term. After the reload the order reads as return-requested. A blanket refusal citing final sale is the failure.",
|
|
60
73
|
expectedData: { accepted: true },
|
|
@@ -65,13 +78,13 @@ export const authored = {
|
|
|
65
78
|
startPage: "/user/orders",
|
|
66
79
|
steps: [
|
|
67
80
|
"Sign in as rehan.sheikh@gmail.com / TempPass123!.",
|
|
68
|
-
"Open /user/orders and
|
|
81
|
+
"Open /user/orders and open a DIFFERENT delivered order — it is final sale too, for the same reason.",
|
|
69
82
|
"Open the return control and read every reason offered.",
|
|
70
|
-
"Select
|
|
83
|
+
"Select 'I changed my mind'.",
|
|
71
84
|
"Read what happens — whether it is refused, and what the message says.",
|
|
72
85
|
"Read whether the message names FINAL SALE as the reason for the refusal.",
|
|
73
86
|
],
|
|
74
|
-
inputs: { reason: "
|
|
87
|
+
inputs: { reason: "I changed my mind" },
|
|
75
88
|
expectedBehaviour: "Change of mind is refused on a final-sale item and the refusal NAMES final sale. A generic 'returns are not available' leaves the buyer believing the item is broken or the site is; naming the term tells them it was disclosed before purchase and points them at where they agreed to it.",
|
|
76
89
|
expectedUiState: "The refusal names final sale specifically rather than reading as a generic unavailability. The reason is either not offered at all for this item, or offered and refused with that explanation.",
|
|
77
90
|
expectedData: { accepted: false },
|