@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.
Files changed (181) hide show
  1. package/dist/_internal/server/features/offers/adapters.d.ts +29 -7
  2. package/dist/_internal/server/features/offers/adapters.js +14 -3
  3. package/dist/_internal/server/features/orders/adapters.js +54 -1
  4. package/dist/client.d.ts +1 -0
  5. package/dist/client.js +1 -0
  6. package/dist/features/account/components/UserOrdersView.js +30 -2
  7. package/dist/features/account/hooks/useAddresses.d.ts +21 -6
  8. package/dist/features/account/hooks/useAddresses.js +1 -1
  9. package/dist/features/addresses/hooks/usePostalLookup.js +84 -12
  10. package/dist/features/admin/components/AdminCategoriesView.js +37 -2
  11. package/dist/features/admin/components/AdminOffersView.js +2 -2
  12. package/dist/features/admin/constants/filter-tabs.d.ts +25 -0
  13. package/dist/features/admin/constants/filter-tabs.js +30 -0
  14. package/dist/features/admin/hooks/useAdminListingData.d.ts +35 -0
  15. package/dist/features/admin/hooks/useAdminListingData.js +45 -9
  16. package/dist/features/cart/schemas/index.d.ts +15 -0
  17. package/dist/features/cart/schemas/index.js +2 -0
  18. package/dist/features/cart/types/index.d.ts +22 -0
  19. package/dist/features/categories/components/CategoriesIndexListing.js +19 -1
  20. package/dist/features/categories/components/CategoriesIndexPageView.js +14 -1
  21. package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +8 -0
  22. package/dist/features/classified/components/ClassifiedDetailPageView.js +1 -0
  23. package/dist/features/events/actions/event-actions.d.ts +13 -0
  24. package/dist/features/events/actions/event-actions.js +75 -1
  25. package/dist/features/events/repository/event-entry.repository.d.ts +17 -0
  26. package/dist/features/events/repository/event-entry.repository.js +36 -0
  27. package/dist/features/homepage/components/BrandsSection.js +1 -1
  28. package/dist/features/homepage/components/CustomerReviewsSection.js +1 -1
  29. package/dist/features/homepage/components/FeaturedBundlesSection.js +1 -1
  30. package/dist/features/homepage/components/ShopByCategorySection.js +1 -1
  31. package/dist/features/media/upload/MediaUploadField.js +21 -3
  32. package/dist/features/orders/components/OrdersList.js +2 -1
  33. package/dist/features/orders/index.d.ts +1 -0
  34. package/dist/features/orders/index.js +1 -0
  35. package/dist/features/orders/types/index.d.ts +2 -0
  36. package/dist/features/orders/utils/order-ref.d.ts +45 -0
  37. package/dist/features/orders/utils/order-ref.js +58 -0
  38. package/dist/features/products/components/MakeOfferButton.d.ts +18 -1
  39. package/dist/features/products/components/MakeOfferButton.js +23 -1
  40. package/dist/features/products/components/ProductDetailPageView.d.ts +5 -0
  41. package/dist/features/products/components/ProductDetailPageView.js +3 -2
  42. package/dist/features/products/repository/products.repository.js +29 -2
  43. package/dist/features/seller/actions/offer-actions.js +32 -0
  44. package/dist/features/seller/components/QuickProductForm.js +15 -1
  45. package/dist/features/seller/components/SellerBidsView.js +3 -1
  46. package/dist/features/seller/components/SellerOffersView.js +2 -2
  47. package/dist/features/seller/components/SellerOrdersView.js +49 -6
  48. package/dist/features/seller/components/SellerProductsCards.js +23 -1
  49. package/dist/features/seller/components/SellerProductsView.js +27 -2
  50. package/dist/features/seller/hooks/useSellerListingData.d.ts +0 -1
  51. package/dist/features/seller/hooks/useSellerListingData.js +17 -19
  52. package/dist/features/shell/SectionForm.js +33 -2
  53. package/dist/features/tester/seed-data/_happy-path.d.ts +23 -0
  54. package/dist/features/tester/seed-data/_happy-path.js +710 -0
  55. package/dist/features/tester/seed-data/_money-flows.js +34 -23
  56. package/dist/features/tester/seed-data/authored/account-auth__profile-settings.js +22 -3
  57. package/dist/features/tester/seed-data/authored/addresses__address-filters.js +17 -12
  58. package/dist/features/tester/seed-data/authored/addresses__postal-lookup.js +7 -6
  59. package/dist/features/tester/seed-data/authored/addresses__postal-validation.js +10 -4
  60. package/dist/features/tester/seed-data/authored/addresses__state-picker.js +13 -8
  61. package/dist/features/tester/seed-data/authored/addresses__unban-request.js +49 -11
  62. package/dist/features/tester/seed-data/authored/admin__admin-detail-round-trips.js +10 -6
  63. package/dist/features/tester/seed-data/authored/admin__bans-and-trust.js +71 -32
  64. package/dist/features/tester/seed-data/authored/admin__blog-faqs.js +80 -31
  65. package/dist/features/tester/seed-data/authored/admin__bug-hunter-rewards.js +62 -25
  66. package/dist/features/tester/seed-data/authored/admin__bulk-actions.js +61 -31
  67. package/dist/features/tester/seed-data/authored/admin__bundles.js +84 -37
  68. package/dist/features/tester/seed-data/authored/admin__buyer-data-admin.js +90 -57
  69. package/dist/features/tester/seed-data/authored/admin__catalog-listings.js +38 -26
  70. package/dist/features/tester/seed-data/authored/admin__category-brand-authoring.js +47 -28
  71. package/dist/features/tester/seed-data/authored/admin__classifieds-digitalcodes-live.js +118 -31
  72. package/dist/features/tester/seed-data/authored/admin__content-deletes.js +30 -24
  73. package/dist/features/tester/seed-data/authored/admin__content-marketing.js +83 -46
  74. package/dist/features/tester/seed-data/authored/admin__coupons.js +8 -8
  75. package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +9 -9
  76. package/dist/features/tester/seed-data/authored/admin__firebase-function-effects.js +19 -4
  77. package/dist/features/tester/seed-data/authored/admin__media-watermark.js +77 -33
  78. package/dist/features/tester/seed-data/authored/admin__orders-fulfillment.js +5 -5
  79. package/dist/features/tester/seed-data/authored/admin__prize-draws-lotteries.js +29 -5
  80. package/dist/features/tester/seed-data/authored/admin__site-system.js +45 -23
  81. package/dist/features/tester/seed-data/authored/admin__uncovered-admin-pages.js +53 -28
  82. package/dist/features/tester/seed-data/authored/admin__users-trust.js +20 -20
  83. package/dist/features/tester/seed-data/authored/buying__bidding.js +19 -2
  84. package/dist/features/tester/seed-data/authored/buying__browsing-search.js +20 -5
  85. package/dist/features/tester/seed-data/authored/buying__buying-checkout.js +28 -10
  86. package/dist/features/tester/seed-data/authored/buying__cart.js +10 -3
  87. package/dist/features/tester/seed-data/authored/buying__image-tile-layout.js +0 -16
  88. package/dist/features/tester/seed-data/authored/buying__my-orders.js +27 -5
  89. package/dist/features/tester/seed-data/authored/buying__offers.js +22 -7
  90. package/dist/features/tester/seed-data/authored/buying__order-detail-actions.js +3 -3
  91. package/dist/features/tester/seed-data/authored/buying__product-detail.js +35 -4
  92. package/dist/features/tester/seed-data/authored/buying__return-request.js +19 -6
  93. package/dist/features/tester/seed-data/authored/buying__reviews-pagination.js +36 -18
  94. package/dist/features/tester/seed-data/authored/buying__reviews.js +16 -1
  95. package/dist/features/tester/seed-data/authored/buying__user-dashboard-navigation.js +2 -1
  96. package/dist/features/tester/seed-data/authored/buying__user-uncovered-pages.js +16 -1
  97. package/dist/features/tester/seed-data/authored/community-support__public-profile.js +3 -2
  98. package/dist/features/tester/seed-data/authored/community-support__support-tickets.js +4 -4
  99. package/dist/features/tester/seed-data/authored/content-discovery__blog.js +19 -2
  100. package/dist/features/tester/seed-data/authored/content-discovery__category-brand-relations.js +4 -4
  101. package/dist/features/tester/seed-data/authored/content-discovery__category-counts-and-rollup.js +5 -5
  102. package/dist/features/tester/seed-data/authored/content-discovery__coupons.js +41 -6
  103. package/dist/features/tester/seed-data/authored/content-discovery__event-detail-subroutes.js +63 -8
  104. package/dist/features/tester/seed-data/authored/content-discovery__event-participation.js +29 -29
  105. package/dist/features/tester/seed-data/authored/content-discovery__events.js +2 -2
  106. package/dist/features/tester/seed-data/authored/content-discovery__faq-help.js +23 -1
  107. package/dist/features/tester/seed-data/authored/content-discovery__notifications.js +6 -6
  108. package/dist/features/tester/seed-data/authored/content-discovery__search.js +1 -1
  109. package/dist/features/tester/seed-data/authored/content-discovery__store-reviews-aggregate.js +1 -1
  110. package/dist/features/tester/seed-data/authored/cta-layout__checkout-bottom-bar.js +31 -6
  111. package/dist/features/tester/seed-data/authored/cta-layout__dialog-footers.js +34 -10
  112. package/dist/features/tester/seed-data/authored/cta-layout__editor-action-bar.js +35 -8
  113. package/dist/features/tester/seed-data/authored/cta-layout__navbar-ctas.js +31 -9
  114. package/dist/features/tester/seed-data/authored/cta-layout__product-bottom-bar.js +29 -3
  115. package/dist/features/tester/seed-data/authored/design-ux__back-to-top-button.js +1 -1
  116. package/dist/features/tester/seed-data/authored/design-ux__carousel-arrow-bounds.js +10 -10
  117. package/dist/features/tester/seed-data/authored/design-ux__dashboard-layout.js +3 -3
  118. package/dist/features/tester/seed-data/authored/design-ux__footer-theme.js +2 -2
  119. package/dist/features/tester/seed-data/authored/design-ux__form-validation-errors.js +2 -2
  120. package/dist/features/tester/seed-data/authored/design-ux__general-design.js +4 -4
  121. package/dist/features/tester/seed-data/authored/design-ux__hand-mode-layout.js +1 -1
  122. package/dist/features/tester/seed-data/authored/design-ux__homepage-carousels.js +8 -8
  123. package/dist/features/tester/seed-data/authored/design-ux__status-badge-legibility.js +2 -2
  124. package/dist/features/tester/seed-data/authored/design-ux__sticky-cta-bar.js +2 -2
  125. package/dist/features/tester/seed-data/authored/page-wiring__data-loss.js +39 -16
  126. package/dist/features/tester/seed-data/authored/page-wiring__detail-pages.js +43 -8
  127. package/dist/features/tester/seed-data/authored/page-wiring__drawer-pages.js +40 -14
  128. package/dist/features/tester/seed-data/authored/page-wiring__reachability.js +31 -14
  129. package/dist/features/tester/seed-data/authored/public-pages__auth-error-pages.js +7 -6
  130. package/dist/features/tester/seed-data/authored/public-pages__bug-hunters.js +14 -5
  131. package/dist/features/tester/seed-data/authored/public-pages__core-listing-pages.js +3 -3
  132. package/dist/features/tester/seed-data/authored/public-pages__help-how-it-works.js +1 -1
  133. package/dist/features/tester/seed-data/authored/public-pages__help-scams-guides-subpages.js +4 -2
  134. package/dist/features/tester/seed-data/authored/public-pages__legal-policy-pages.js +3 -3
  135. package/dist/features/tester/seed-data/authored/public-pages__newly-wired-browse-indexes.js +5 -5
  136. package/dist/features/tester/seed-data/authored/public-pages__store-tabs.js +5 -5
  137. package/dist/features/tester/seed-data/authored/public-pages__stores-sellers-directories.js +3 -3
  138. package/dist/features/tester/seed-data/authored/search-and-nav__employee-permissions.js +45 -11
  139. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +57 -17
  140. package/dist/features/tester/seed-data/authored/search-and-nav__settings-deep-links.js +36 -5
  141. package/dist/features/tester/seed-data/authored/search-and-nav__sidebar-search.js +29 -4
  142. package/dist/features/tester/seed-data/authored/selling__become-seller.js +23 -0
  143. package/dist/features/tester/seed-data/authored/selling__final-sale-authoring.js +14 -13
  144. package/dist/features/tester/seed-data/authored/selling__listing-a-product.js +14 -9
  145. package/dist/features/tester/seed-data/authored/selling__listing-edit-roundtrip.js +34 -7
  146. package/dist/features/tester/seed-data/authored/selling__listing-lifecycle.js +17 -7
  147. package/dist/features/tester/seed-data/authored/selling__listing-type-fields-roundtrip.js +9 -9
  148. package/dist/features/tester/seed-data/authored/selling__media-limits.js +9 -4
  149. package/dist/features/tester/seed-data/authored/selling__product-upload-details.js +3 -3
  150. package/dist/features/tester/seed-data/authored/selling__quick-add-minimum-details.js +3 -3
  151. package/dist/features/tester/seed-data/authored/selling__sectionised-forms.js +25 -1
  152. package/dist/features/tester/seed-data/authored/selling__seller-analytics-payouts.js +27 -6
  153. package/dist/features/tester/seed-data/authored/selling__seller-bids-bundles-filters.js +19 -1
  154. package/dist/features/tester/seed-data/authored/selling__seller-catalog-org.js +63 -22
  155. package/dist/features/tester/seed-data/authored/selling__seller-custom-brands.js +9 -5
  156. package/dist/features/tester/seed-data/authored/selling__seller-guide.js +7 -6
  157. package/dist/features/tester/seed-data/authored/selling__seller-listing-types.js +3 -2
  158. package/dist/features/tester/seed-data/authored/selling__seller-marketing-extras.js +18 -18
  159. package/dist/features/tester/seed-data/authored/selling__seller-ops-comms.js +13 -12
  160. package/dist/features/tester/seed-data/authored/selling__seller-orders-at-scale.js +19 -3
  161. package/dist/features/tester/seed-data/authored/selling__seller-orders.js +22 -4
  162. package/dist/features/tester/seed-data/authored/selling__seller-shipping-payouts-setup.js +20 -8
  163. package/dist/features/tester/seed-data/authored/selling__store-dashboard-navigation.js +4 -4
  164. package/dist/features/tester/seed-data/authored/selling__store-uncovered-pages.js +2 -2
  165. package/dist/features/tester/seed-data/authored/seo__canonical-and-host.js +5 -5
  166. package/dist/features/tester/seed-data/authored/seo__og-images.js +1 -1
  167. package/dist/features/tester/seed-data/authored/seo__page-metadata.js +7 -7
  168. package/dist/features/tester/seed-data/authored/seo__sitemap-and-robots.js +3 -3
  169. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +123 -21
  170. package/dist/features/tester/utils/phases.d.ts +17 -0
  171. package/dist/features/tester/utils/phases.js +29 -2
  172. package/dist/index.d.ts +1 -0
  173. package/dist/index.js +2 -0
  174. package/dist/seo/json-ld.d.ts +23 -0
  175. package/dist/seo/json-ld.js +3 -2
  176. package/dist/server.d.ts +1 -0
  177. package/dist/server.js +2 -0
  178. package/dist/styles.css +1 -1
  179. package/dist/tailwind-utilities.css +1 -1
  180. package/dist/ui/components/PaginatedSelect.js +0 -0
  181. package/package.json +1 -1
@@ -43,10 +43,10 @@ export const authored = {
43
43
  },
44
44
  "checklist-selling-seller-ops-comms-seller-fulfillment-queue": {
45
45
  roles: ["seller"],
46
- startPage: "/store/orders",
46
+ startPage: "/store/fulfillment",
47
47
  steps: [
48
48
  "Sign in as tyson@beybladearena.in / TempPass123!.",
49
- "Open the store's fulfillment queue and read the rows.",
49
+ "Open /store/fulfillment and stay on its Queue tab — the page is a two-tab shell, Queue and 'Print centre', and the other tab is a different case.",
50
50
  "Read each row's primary label and check it names the ITEM rather than only an order id.",
51
51
  "Read every filter offered and select each in turn, reading the rows.",
52
52
  "Open one row and read the order it opens.",
@@ -61,7 +61,8 @@ export const authored = {
61
61
  startPage: "/store/print-center",
62
62
  steps: [
63
63
  "Sign in as tyson@beybladearena.in / TempPass123!.",
64
- "Open /store/print-center and read what it offers.",
64
+ "Open /store/print-center and note that it REDIRECTS to /store/fulfillment, carrying the query string with it. Landing on a differently-named page is expected, not a fault.",
65
+ "Switch to the 'Print centre' tab — note the British spelling — and read what it offers.",
65
66
  "Select one or more items or orders to print.",
66
67
  "Read the preview and check the store's own name, logo and address appear on it.",
67
68
  "Generate the printable output and read it.",
@@ -73,17 +74,17 @@ export const authored = {
73
74
  },
74
75
  "checklist-selling-seller-ops-comms-seller-inventory-print": {
75
76
  roles: ["seller"],
76
- startPage: "/store/print-center",
77
+ startPage: "/store/fulfillment",
77
78
  steps: [
78
79
  "Sign in as tyson@beybladearena.in / TempPass123!.",
79
- "Open /store/print-center and write down what it offers and whether the store context is present.",
80
- "Open the store's inventory print page.",
81
- "Write down what IT offers and whether the store context is present.",
82
- "Compare the two side by side.",
83
- "Check the sidebar for which of the two is linked.",
80
+ "Open /store/fulfillment, switch to the 'Print centre' tab, and write down what it offers and whether the store context is present — name, logo, pickup address.",
81
+ "Open /store/inventory/print directly by URL. It should NOT resolve: the degraded duplicate was removed when Print Centre became a tab.",
82
+ "Open /store/print-center and confirm it redirects here rather than rendering a second copy.",
83
+ "Read the sidebar and check exactly ONE entry leads to this surface, under whichever name it uses.",
84
+ "Confirm there is no second, store-less print surface reachable from anywhere in the sidebar.",
84
85
  ],
85
- expectedBehaviour: "Only one of these is the real surface. The other renders the same component with no store attached, so it produces a preview with no name, no logo and no address — a page that looks built and yields an unusable label. Two features that look alike is how one ships broken and unnoticed.",
86
- expectedUiState: "One surface carries the full store context and the other does not, or the second no longer exists. Record which is which, and which one the sidebar links to — a sidebar pointing at the degraded copy is the finding.",
87
- endResult: "Read-only; nothing persists. If both render identically and correctly, say so — that is a valid outcome and means the duplicate was resolved.",
86
+ expectedBehaviour: "The duplicate is RESOLVED and this case now guards the resolution rather than measuring the gap. /store/inventory/print used to render the same component with no store attached — a preview with no name, no logo and no address, a page that looked built and produced an unusable label. It was removed when Print Centre became a tab of /store/fulfillment, and /store/print-center became a redirect. What must stay true is that exactly one print surface exists and it has the store context.",
87
+ expectedUiState: "The Print centre tab carries the store name, logo and pickup address. /store/inventory/print does not resolve. /store/print-center redirects here rather than rendering a second copy. The sidebar offers exactly one route to it. A second print surface reappearing — or this one rendering without store context — is the finding.",
88
+ endResult: "Read-only; nothing persists. /store/inventory/print resolving at all is a REGRESSION, not a discovery: it was deliberately deleted, so its return means something reinstated it.",
88
89
  },
89
90
  };
@@ -44,12 +44,28 @@ export const authored = {
44
44
  steps: [
45
45
  "Sign in as tyson@beybladearena.in / TempPass123!.",
46
46
  "Open /store/orders and count how many orders are listed.",
47
+ /*
48
+ * 🛑 ZERO IS ONE FAILURE HERE; TOO HIGH IS THE OTHER, AND ONLY ZERO WAS
49
+ * BEING CHECKED.
50
+ *
51
+ * The route documents two real bugs it fixed, and this case only caught
52
+ * the first: an unbounded `in` query that threw for any store past its
53
+ * 30th listing and was swallowed into ₹0 (Root Cause #59's shape). The
54
+ * second was the opposite direction — `o.status !== "CANCELLED"` against
55
+ * a lowercase OrderStatusValues, so the exclusion never excluded anything
56
+ * and headline revenue counted cancelled and refunded orders.
57
+ *
58
+ * A "> ₹0" assertion passes cheerfully against that. The cancelled and
59
+ * refunded totals are what tell the two apart, so the steps below read
60
+ * them.
61
+ */
62
+ "Filter /store/orders to Cancelled and note the total of any one cancelled order.",
47
63
  "Open /store.",
48
64
  "Read the total-orders figure and the revenue figure on the dashboard.",
49
65
  ],
50
- expectedBehaviour: "The dashboard's headline numbers come from the same query as the order list, so they must agree with it. A failed query here is swallowed into an empty array, which renders as a confident zero rather than as an error.",
51
- expectedUiState: "The order count matches what /store/orders listed, and revenue is greater than ₹0 for a store with delivered orders.",
52
- expectedData: { revenueIsZero: false },
66
+ expectedBehaviour: "The dashboard's headline numbers come from the same query as the order list, so they must agree with it. A failed query here is swallowed into an empty array, which renders as a confident zero rather than as an error. Revenue additionally EXCLUDES cancelled and refunded orders — money that was never kept is not revenue — so a figure that silently includes them is wrong in the opposite direction and looks healthier than the truth.",
67
+ expectedUiState: "The order count matches what /store/orders listed, and revenue is greater than ₹0 for a store with delivered orders. Revenue is also strictly LESS than the sum of every order's total, because this store has cancelled and refunded orders that must not be counted — a revenue figure equal to the all-orders sum is the exclusion silently not applying.",
68
+ expectedData: { revenueIsZero: false, cancelledOrdersCountedAsRevenue: false },
53
69
  endResult: "The same figures survive a reload.",
54
70
  },
55
71
  "checklist-selling-seller-orders-at-scale-orders-only-this-store": {
@@ -135,13 +135,31 @@ export const authored = {
135
135
  steps: [
136
136
  "Sign in as tyson@beybladearena.in / TempPass123!.",
137
137
  "Open /store/orders and open an order.",
138
- "Find the WhatsApp share control and read what it offers.",
139
- "Trigger it and read the message it composes before sending anything.",
140
- "Check the message for the buyer's full phone number, full address and any payment identifier.",
138
+ /*
139
+ * 🛑 NO SUCH CONTROL EXISTS TODAY, AND ABSENCE IS THE EXPECTED ANSWER.
140
+ *
141
+ * Measured 2026-09-29: SELLER_ROW_ACTIONS.orders is
142
+ * [VIEW, EDIT, TRACK, RESEND] — no share. SellerOrdersView mentions
143
+ * WhatsApp only as the buyer's purchased add-on flag
144
+ * (whatsappNotifyAddon / whatsappNotifyFee), and every `wa.me` link in
145
+ * the codebase is on the contact page, the chat button or the buyer's own
146
+ * payment page. The registry's WhatsApp actions are store SETUP
147
+ * (whatsapp-connect, catalog-sync, catalog-import).
148
+ *
149
+ * The case is kept rather than deleted because it guards a real risk the
150
+ * day someone adds one: an order share is exactly the control that would
151
+ * paste a buyer's address and phone into a third-party app. Written so
152
+ * that absence PASSES and a leaky implementation FAILS — which is the
153
+ * only shape that stays useful while the feature does not exist.
154
+ */
155
+ "Look for a WhatsApp or generic share control on the order — in the row actions, the detail drawer and the full detail page.",
156
+ "If none exists anywhere, record that and stop: no share control is the expected state and the case passes.",
157
+ "If one does exist, trigger it and read the message it composes before sending anything.",
158
+ "Check that message for the buyer's full phone number, full address and any payment identifier.",
141
159
  "Close without sending.",
142
160
  ],
143
161
  expectedBehaviour: "The share composes a message about the order. What it must not do is put more of the buyer's data into a third-party app than the seller needs to fulfil — a share that pastes a full address and phone into an outbound message has moved PII somewhere no policy here covers.",
144
- expectedUiState: "The composed message identifies the order and what it contains. Read exactly what buyer data it includes and record it. A full payment identifier in the message is a finding regardless of anything else.",
162
+ expectedUiState: "No share control is present on the row actions, the drawer or the detail page — that is the current expected state and it passes. If one IS present, the composed message identifies the order and what it contains; read exactly what buyer data it includes and record it, and a full payment identifier in that message is a finding regardless of anything else.",
145
163
  endResult: "Nothing is sent. Report precisely which buyer fields the message carries — that is the substance of this case.",
146
164
  },
147
165
  "checklist-selling-seller-orders-seller-auction-forfeit-notification": {
@@ -25,7 +25,7 @@ export const authored = {
25
25
  startPage: "/store/shipping",
26
26
  steps: [
27
27
  "Sign in as tyson@beybladearena.in / TempPass123!.",
28
- "Open the store's shipping settings and read every field and section.",
28
+ "Open /store/shipping and read every field and section.",
29
29
  "Note which shipping options the store currently offers and their rates.",
30
30
  "Read whether a free-shipping threshold is configurable and what it is set to.",
31
31
  "Reload the page and confirm the same values are shown.",
@@ -39,10 +39,10 @@ export const authored = {
39
39
  startPage: "/store/shipping",
40
40
  steps: [
41
41
  "Sign in as tyson@beybladearena.in / TempPass123!.",
42
- "Open the store's shipping settings and create a config named 'QA Shipping configs-crud' with a rate of 99.",
42
+ "Open /store/shipping and create a config named 'QA Shipping configs-crud' with a rate of 99.",
43
43
  "Save, RELOAD, and read every field of it.",
44
44
  "Edit only its rate to 149, save, RELOAD, and read every field again including the name.",
45
- "Open a product's editor and check the new config is offered as a shipping choice.",
45
+ "Open /store/products, then that product's editor, and check the new config is offered as a shipping choice.",
46
46
  "Delete the config and RELOAD to confirm.",
47
47
  ],
48
48
  inputs: { name: "QA Shipping configs-crud", rateBefore: 99, rateAfter: 149 },
@@ -73,7 +73,7 @@ export const authored = {
73
73
  startPage: "/store/payouts",
74
74
  steps: [
75
75
  "Sign in as tyson@beybladearena.in / TempPass123!.",
76
- "Open the store's payout settings and read every field and toggle.",
76
+ "Open /store/payouts and read every field and toggle.",
77
77
  "Read whether the payout schedule, hold period and minimum amount are shown.",
78
78
  "Change one editable setting and save.",
79
79
  "RELOAD and read every setting again.",
@@ -88,13 +88,25 @@ export const authored = {
88
88
  startPage: "/store/shipping",
89
89
  steps: [
90
90
  "Sign in as tyson@beybladearena.in / TempPass123!.",
91
- "Open each of the pre-consolidation URLs directly in the address bar, one at a time.",
91
+ /*
92
+ * 🛑 THE URLS ARE NAMED NOW. This said "each of the pre-consolidation
93
+ * URLs" and listed none, so the tester had to guess which ones existed —
94
+ * and a guess that misses the one that regressed reports a clean pass.
95
+ *
96
+ * These are the real shims under /store, each a page.tsx whose whole body
97
+ * is a redirect. Two of them carry a TAB, which is the part worth
98
+ * checking: /store/payout-settings redirects to ?tab=settings, and
99
+ * /store/print-center forwards its own query onto /store/fulfillment.
100
+ * Landing on the right page but the FIRST tab is the regression this case
101
+ * exists for, and it is invisible unless the URLs are enumerated.
102
+ */
103
+ "Open each of these pre-consolidation URLs directly in the address bar, one at a time: /store/payout-methods, /store/payout-settings, /store/shipping-configs, /store/print-center, /store/auctions, /store/pre-orders, /store/prize-draws, /store/slug.",
92
104
  "For each, read where the browser lands and which tab is open.",
93
105
  "Note any that 404 or land on the first tab rather than the one they name.",
94
106
  "Read the final URL each one settles on.",
95
107
  ],
96
108
  expectedBehaviour: "An old URL lands on the consolidated page WITH its own tab open. These URLs are live in bookmarks, emails and guides, so a 404 breaks links that were correct when they were written — and landing on tab one is only marginally better, since the user still has to hunt.",
97
- expectedUiState: "Every old URL resolves and opens the tab it corresponds to. None 404s and none lands on the default tab. Record any that do, by URL.",
109
+ expectedUiState: "Every old URL resolves and opens the tab it corresponds to. None 404s and none lands on the default tab. Specifically: /store/payout-settings settles on /store/payouts with the settings tab open (its shim appends ?tab=settings), /store/payout-methods settles on /store/payouts, /store/shipping-configs on /store/shipping, /store/print-center on /store/fulfillment carrying any query it was given, /store/slug on /store/storefront, and /store/auctions, /store/pre-orders and /store/prize-draws each on /store/products carrying its own ?listingType= (auction, pre-order, prize-draw) — arriving without that parameter is the regression, because the page then shows every type. Record any that 404 or land on the default tab, by URL.",
98
110
  endResult: "Read-only; nothing persists.",
99
111
  },
100
112
  "checklist-selling-seller-shipping-payouts-setup-consolidated-tabs-url-writeback": {
@@ -102,7 +114,7 @@ export const authored = {
102
114
  startPage: "/store/shipping",
103
115
  steps: [
104
116
  "Sign in as tyson@beybladearena.in / TempPass123!.",
105
- "Open the consolidated settings page and read the URL.",
117
+ "Open /store/shipping and read the URL. It is the consolidated page: /store/shipping-configs now redirects here, as /store/payout-methods and /store/payout-settings both redirect to /store/payouts.",
106
118
  "Click a different tab and read the URL again.",
107
119
  "Copy that URL, open it in a new tab, and read which tab is open.",
108
120
  "Press the browser back button and read which tab is shown.",
@@ -117,7 +129,7 @@ export const authored = {
117
129
  startPage: "/store/print-center",
118
130
  steps: [
119
131
  "Sign in as tyson@beybladearena.in / TempPass123!.",
120
- "Open /store/print-center and select two items to print.",
132
+ "Open /store/print-center — it REDIRECTS to /store/fulfillment and carries the query string with it, which is the whole mechanism this case depends on — then switch to the 'Print centre' tab and select two items to print.",
121
133
  "Read the URL and check the selection is represented in it.",
122
134
  "Copy the URL and open it in a new tab.",
123
135
  "Read whether the same two items are selected on arrival.",
@@ -25,10 +25,10 @@ export const authored = {
25
25
  startPage: "/store",
26
26
  steps: [
27
27
  "Sign in as tyson@beybladearena.in / TempPass123!.",
28
- "Open /store and expand every group in the sidebar.",
28
+ "Open /store and expand ALL SIX sidebar groups: Overview, Listings, Orders & Reviews, Finance, Store, Guides. The last one — Guides — sets defaultOpen:false, so it is the one a tester skips and then reports as missing.",
29
29
  "Click each link in turn, reading where it lands and going back each time.",
30
30
  "Write down any link that 404s, renders an empty shell, or lands somewhere unrelated.",
31
- "Count the links against the number of pages that exist under /store.",
31
+ "Count the links against the pages that exist under /store. There are 39 sidebar items and 86 page.tsx files beneath /store, so a surplus of pages is EXPECTED — new/, [id]/edit/ and other sub-routes legitimately have no entry of their own. What matters is a top-level page with no route in at all.",
32
32
  ],
33
33
  expectedBehaviour: "Every sidebar link opens a real page with content. The inverse — a built page with no sidebar entry — is the same defect from the other side and is why the count matters: around seventeen store pages were once reachable only by typing their exact URL.",
34
34
  expectedUiState: "Every link resolves to a page that renders content, not a 404 and not chrome with an empty body. Note any page you know exists that has no link — that half is not enforced and has to be spotted by eye.",
@@ -42,7 +42,7 @@ export const authored = {
42
42
  "Sign in as tyson@beybladearena.in / TempPass123!.",
43
43
  "Open /store and note which sidebar entry is highlighted.",
44
44
  "Navigate to /store/products and read which entry is highlighted.",
45
- "Navigate to a nested page beneath it — a product's editor — and read the highlight again.",
45
+ "Navigate to a nested page beneath it — open /store/products, then a product's editor at /store/products/{id}/edit — and read the highlight again. The parent Products entry must stay highlighted two levels down; a highlight that only matches the exact path goes dark on every editor.",
46
46
  "Navigate to /store/orders and read it again.",
47
47
  "Use the browser's back button and read the highlight.",
48
48
  ],
@@ -94,7 +94,7 @@ export const authored = {
94
94
  "Click through to /user and read where it lands.",
95
95
  "From /user, find the way back to /store and click it.",
96
96
  "Check the sidebar changed with the portal each time.",
97
- "Open the public store page from within the dashboard and confirm it opens the public view rather than the editor.",
97
+ "Open the public store page from within the dashboard — it is /stores/store-beyblade-arena, under the PLURAL /stores — and confirm it opens the public view rather than the editor. The two differ by one character, which is exactly how such a link ends up pointing back into the dashboard.",
98
98
  ],
99
99
  expectedBehaviour: "A seller is also a buyer, so both portals are reachable from each other and each renders its own navigation. The public-store link is a distinct destination from the store settings editor — conflating them is a live defect on the buyer side, where a 'My Profile' entry leads to the edit page rather than the public profile.",
100
100
  expectedUiState: "Each cross-link lands in the other portal with that portal's own sidebar. The public store link opens the public store page, not the settings editor.",
@@ -69,7 +69,7 @@ export const authored = {
69
69
  startPage: "/store/pre-orders",
70
70
  steps: [
71
71
  SIGN_IN_SELLER,
72
- "Open /store/pre-orders.",
72
+ "Open /store/pre-orders. It REDIRECTS to /store/products?listingType=pre-order — the per-type seller pages were folded into the one products list with a type filter — so landing on a differently-named URL carrying a query is the design, not a broken link. Everything below is read on that filtered list.",
73
73
  "Read the listings shown and check each is a pre-order.",
74
74
  "Read each one's production status and delivery date in the list.",
75
75
  "Create a pre-order from this page titled 'QA Store Preorder Probe' with a full price of 999 and a deposit of 200.",
@@ -86,7 +86,7 @@ export const authored = {
86
86
  steps: [
87
87
  SIGN_IN_SELLER,
88
88
  "Open each of these by URL in turn: /store/guide, /store/guide/capabilities, /store/guide/finance, /store/guide/listings, /store/guide/orders, /store/guide/settings and /store/guide/whatsapp.",
89
- "Check every one of them is also linked from the Guide area rather than only reachable by URL.",
89
+ "Check every one of them is also linked from the sidebar's 'Guides' group — it is the LAST group and sets defaultOpen:false, so EXPAND IT before concluding anything is unlinked. All seven are there: All Guides, Listings Guide, Orders Guide, Finance Guide, Settings, Capabilities, WhatsApp Catalog Sync.",
90
90
  "Record any that 404 or render empty.",
91
91
  "On two of them, check the screen they describe still exists and is named the same way.",
92
92
  "Record any guide describing a control that is no longer there.",
@@ -55,7 +55,7 @@ export const authored = {
55
55
  "Type the products path with an /en prefix in front of it into the address bar.",
56
56
  "Watch the network panel and read the first response's status.",
57
57
  "Read where the address bar lands.",
58
- "Open the products page from the site's own navigation and read the address bar.",
58
+ "Open /products from the site's own navigation — the Products entry in the main nav, not a typed URL — and read the address bar. It must land on /products with no locale prefix; the site's own links are what matter here, since a typed /en/products would only prove the redirect works, not that the navigation stopped emitting prefixed hrefs.",
59
59
  "Compare the two.",
60
60
  ],
61
61
  expectedBehaviour: "A locale-prefixed path resolves to the unprefixed one, and the site's own links use the unprefixed form so no internal navigation pays the redirect. Two spellings of every path is two addresses a crawler has to reconcile, and one of them is always the slower.",
@@ -66,7 +66,7 @@ export const authored = {
66
66
  roles: ["guest"],
67
67
  startPage: "/",
68
68
  steps: [
69
- "Open the homepage on the www host and view the page source.",
69
+ "Open the homepage on the www host and view the page source. The canonical host has ONE definition — appkit.config.js seo.siteUrl, which defaults to https://www.letitrip.in and can be overridden by NEXT_PUBLIC_SITE_URL. That override is how these drifted apart before: one path read the env var and another held a hardcoded apex, so the sitemap advertised URLs on a host that redirected. Compare what you read here against the host in the address bar, not against a remembered value.",
70
70
  "Find the canonical link element and read its href.",
71
71
  "Compare its host against the host in the address bar.",
72
72
  "Open /products and read its canonical.",
@@ -81,13 +81,13 @@ export const authored = {
81
81
  },
82
82
  "checklist-seo-canonical-and-host-no-inherited-homepage-canonical": {
83
83
  roles: ["guest"],
84
- startPage: "/promotions",
84
+ startPage: "/reviews",
85
85
  steps: [
86
86
  "Open /reviews and view the page source.",
87
87
  "Find the canonical link element, if there is one, and read its href.",
88
88
  "Check it is not the homepage's URL.",
89
- "Open /promotions and read its canonical the same way.",
90
- "Open two more pages that are unlikely to declare their own metadata and read theirs.",
89
+ "Open /promotions and read its canonical the same way. EXPECT NONE: it is a bare redirect, and a redirect page deliberately carries no metadata at all, because redirect() fires before a document is produced — a crawler follows it and reads the canonical of the page it LANDS on. An absent canonical here is correct; the homepage's URL appearing here is the defect.",
90
+ "Open /sellers and /brands — two more pages unlikely to declare their own metadata — and read theirs.",
91
91
  ],
92
92
  expectedBehaviour: "Metadata declared at the root is INHERITED by every page beneath it, so a static absolute canonical there makes every page that does not override it declare itself a duplicate of the homepage. A page either declares its own or has none.",
93
93
  expectedUiState: "No page other than the homepage carries the homepage's URL as its canonical. Every page whose canonical reads as the bare site root is a finding, listed by path.",
@@ -95,7 +95,7 @@ export const authored = {
95
95
  roles: ["guest"],
96
96
  startPage: "/classified/classified-beyblade-stadium-set",
97
97
  steps: [
98
- "Open /classified in a private window and find a listing whose card shows no photo of its own; if every card has one, say so and answer null rather than guessing.",
98
+ "🛑 THIS BRANCH CANNOT BE REACHED THROUGH THE UI — answer null and record why, rather than hunting. The OG renderer falls back when a listing has neither mainImage nor images[0] (resolveOgImageUrl is passed null), but EVERY seeded listing carries images, and both product forms require one: the schema is mainImage: z.string().min(1, 'A main image is required'), on the quick form and the advanced form alike. So no listing a tester can find or create reaches the fallback. Confirm the branch exists by reading the source if you wish, then abstain — a fabricated yes here would be coverage of a path no visitor can produce.",
99
99
  "Open its detail page and view the source.",
100
100
  "Copy the og:image URL and open it in a fresh tab.",
101
101
  "Read what renders.",
@@ -77,10 +77,10 @@ export const authored = {
77
77
  roles: ["guest"],
78
78
  startPage: "/products",
79
79
  steps: [
80
- "Open /products and use the browser's element inspector to count top-level headings.",
81
- "Do the same on the homepage.",
82
- "Do the same on a product detail page.",
83
- "Do the same on a store page and on a blog post.",
80
+ "Open /products and WAIT for the page to settle before counting anything — this app hydrates client-side and the homepage has been measured with NO h1 at 2.5 seconds and exactly one at 3. A count taken early reports zero and reads as a missing heading. Then use the element inspector to count top-level headings.",
81
+ "Do the same on / — the page where the early-count trap was actually measured, so wait there especially.",
82
+ "Do the same on /products/product-beyblade-burst-valkyrie.",
83
+ "Do the same on /stores/store-beyblade-arena and on /blog/selling-tips-letitrip.",
84
84
  "Record the count for each.",
85
85
  ],
86
86
  expectedBehaviour: "One top-level heading per page states what the page is. Several compete to be that statement, and none makes it clear which describes the page.",
@@ -92,11 +92,11 @@ export const authored = {
92
92
  roles: ["guest"],
93
93
  startPage: "/products",
94
94
  steps: [
95
- "Open the network panel and navigate to a product path whose trailing segment is a nonsense word no listing uses.",
95
+ "Open the network panel and navigate to /products/zzzznope — a nonsense slug no listing uses, deliberately NOT shaped like a real id so nobody mistakes it for a fixture.",
96
96
  "Read what the page shows.",
97
97
  "View the source and read every robots meta tag.",
98
- "Repeat with a nonsense store path and a nonsense auction path.",
99
- "Open a REAL product page and read its robots meta tags too.",
98
+ "Repeat with /stores/zzzznope and /auctions/zzzznope.",
99
+ "Open a REAL product page — /products/product-beyblade-burst-valkyrie — and read its robots meta tags too. That contrast is the point: a noindex on the 404 is correct, the SAME noindex on a live listing is the defect, and without both readings you cannot tell which you are looking at.",
100
100
  ],
101
101
  expectedBehaviour: "A missing page renders the site's 404 view and marks itself NOINDEX. Judge the noindex, not the status code: Next streams the response, so the headers are already sent by the time the not-found is raised and the status can no longer be changed. It injects a noindex robots tag into the streamed HTML instead, and that is what actually keeps the URL out of the index. A 200 here is expected and is not the finding.",
102
102
  expectedUiState: "All three missing paths render the 404 view and their source carries a robots tag whose content is noindex. The real product page carries no noindex — check it, because a blanket noindex would satisfy the first half while quietly de-indexing the whole catalogue.",
@@ -49,8 +49,8 @@ export const authored = {
49
49
  startPage: "/robots.txt",
50
50
  steps: [
51
51
  "Open /robots.txt directly and read the whole file.",
52
- "Read every Disallow line.",
53
- "Check no rule disallows the site root for all user agents.",
52
+ "Read every Disallow line. There are ELEVEN under the '*' group — /admin/, /api/, /store/, /user/, /auth/, /checkout/, /cart/, /wishlist, /preview/, /track/, /unauthorized/ — and each names a surface a crawler has no business indexing. A public browse route appearing among them is the finding.",
53
+ "Check no rule disallows the site root for the '*' group. 🛑 THERE IS A SECOND GROUP AND IT DOES DISALLOW EVERYTHING: GPTBot, ChatGPT-User, Google-Extended and CCBot are blocked wholesale with Disallow: /. That is deliberate — AI crawlers, not search engines — so finding a bare 'Disallow: /' in this file is expected and is NOT the failure. Check which user-agent block it sits under before recording anything.",
54
54
  "Read the Host line, if present, and note the hostname.",
55
55
  "Compare that hostname against the address bar and against the sitemap's entries.",
56
56
  ],
@@ -91,7 +91,7 @@ export const authored = {
91
91
  roles: ["guest"],
92
92
  startPage: "/sitemap.xml",
93
93
  steps: [
94
- "Open /sitemap.xml and search for 'sandbox'.",
94
+ "Open /sitemap.xml and search for 'tester-sandbox' — that substring is the exact marker every tester fixture carries in its id, so it is a precise check rather than a guess at the naming.",
95
95
  "Search for 'qa-'.",
96
96
  "Search for 'test-' as a looser check.",
97
97
  "Record any match with its full URL.",