@mohasinac/appkit 4.34.1 → 4.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +32 -2
  2. package/dist/features/tester/components/TesterChecklistStepRow.d.ts +9 -1
  3. package/dist/features/tester/components/TesterChecklistStepRow.js +31 -2
  4. package/dist/features/tester/components/TesterHubView.js +8 -0
  5. package/dist/features/tester/schemas/firestore.d.ts +109 -0
  6. package/dist/features/tester/schemas/firestore.js +14 -0
  7. package/dist/features/tester/seed-data/_money-flows.d.ts +23 -0
  8. package/dist/features/tester/seed-data/_money-flows.js +430 -0
  9. package/dist/features/tester/seed-data/authored/_types.d.ts +33 -0
  10. package/dist/features/tester/seed-data/authored/_types.js +35 -0
  11. package/dist/features/tester/seed-data/authored/account-auth__profile-settings.d.ts +2 -0
  12. package/dist/features/tester/seed-data/authored/account-auth__profile-settings.js +207 -0
  13. package/dist/features/tester/seed-data/authored/account-auth__signup-login.d.ts +2 -0
  14. package/dist/features/tester/seed-data/authored/account-auth__signup-login.js +298 -0
  15. package/dist/features/tester/seed-data/authored/account-auth__testing-program--admin.d.ts +2 -0
  16. package/dist/features/tester/seed-data/authored/account-auth__testing-program--admin.js +33 -0
  17. package/dist/features/tester/seed-data/authored/account-auth__testing-program.d.ts +2 -0
  18. package/dist/features/tester/seed-data/authored/account-auth__testing-program.js +138 -0
  19. package/dist/features/tester/seed-data/authored/addresses__address-filters.d.ts +2 -0
  20. package/dist/features/tester/seed-data/authored/addresses__address-filters.js +36 -0
  21. package/dist/features/tester/seed-data/authored/addresses__postal-lookup.d.ts +2 -0
  22. package/dist/features/tester/seed-data/authored/addresses__postal-lookup.js +75 -0
  23. package/dist/features/tester/seed-data/authored/addresses__postal-validation.d.ts +2 -0
  24. package/dist/features/tester/seed-data/authored/addresses__postal-validation.js +72 -0
  25. package/dist/features/tester/seed-data/authored/addresses__state-picker.d.ts +2 -0
  26. package/dist/features/tester/seed-data/authored/addresses__state-picker.js +54 -0
  27. package/dist/features/tester/seed-data/authored/addresses__unban-request.d.ts +2 -0
  28. package/dist/features/tester/seed-data/authored/addresses__unban-request.js +39 -0
  29. package/dist/features/tester/seed-data/authored/admin__bans-and-trust.d.ts +2 -0
  30. package/dist/features/tester/seed-data/authored/admin__bans-and-trust.js +226 -0
  31. package/dist/features/tester/seed-data/authored/admin__blog-faqs.d.ts +2 -0
  32. package/dist/features/tester/seed-data/authored/admin__blog-faqs.js +82 -0
  33. package/dist/features/tester/seed-data/authored/admin__bulk-actions.d.ts +2 -0
  34. package/dist/features/tester/seed-data/authored/admin__bulk-actions.js +177 -0
  35. package/dist/features/tester/seed-data/authored/admin__bundles.d.ts +2 -0
  36. package/dist/features/tester/seed-data/authored/admin__bundles.js +97 -0
  37. package/dist/features/tester/seed-data/authored/admin__buyer-data-admin.d.ts +2 -0
  38. package/dist/features/tester/seed-data/authored/admin__buyer-data-admin.js +232 -0
  39. package/dist/features/tester/seed-data/authored/admin__catalog-listings.d.ts +2 -0
  40. package/dist/features/tester/seed-data/authored/admin__catalog-listings.js +306 -0
  41. package/dist/features/tester/seed-data/authored/admin__category-brand-authoring.d.ts +2 -0
  42. package/dist/features/tester/seed-data/authored/admin__category-brand-authoring.js +158 -0
  43. package/dist/features/tester/seed-data/authored/admin__classifieds-digitalcodes-live.d.ts +2 -0
  44. package/dist/features/tester/seed-data/authored/admin__classifieds-digitalcodes-live.js +78 -0
  45. package/dist/features/tester/seed-data/authored/admin__content-deletes.d.ts +2 -0
  46. package/dist/features/tester/seed-data/authored/admin__content-deletes.js +261 -0
  47. package/dist/features/tester/seed-data/authored/admin__content-marketing.d.ts +2 -0
  48. package/dist/features/tester/seed-data/authored/admin__content-marketing.js +151 -0
  49. package/dist/features/tester/seed-data/authored/admin__coupons.d.ts +2 -0
  50. package/dist/features/tester/seed-data/authored/admin__coupons.js +214 -0
  51. package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.d.ts +2 -0
  52. package/dist/features/tester/seed-data/authored/admin__events-raffles-spin.js +160 -0
  53. package/dist/features/tester/seed-data/authored/admin__media-watermark.d.ts +2 -0
  54. package/dist/features/tester/seed-data/authored/admin__media-watermark.js +104 -0
  55. package/dist/features/tester/seed-data/authored/admin__orders-fulfillment.d.ts +2 -0
  56. package/dist/features/tester/seed-data/authored/admin__orders-fulfillment.js +350 -0
  57. package/dist/features/tester/seed-data/authored/admin__prize-draws-lotteries.d.ts +2 -0
  58. package/dist/features/tester/seed-data/authored/admin__prize-draws-lotteries.js +105 -0
  59. package/dist/features/tester/seed-data/authored/admin__site-system.d.ts +2 -0
  60. package/dist/features/tester/seed-data/authored/admin__site-system.js +590 -0
  61. package/dist/features/tester/seed-data/authored/admin__uncovered-admin-pages.d.ts +2 -0
  62. package/dist/features/tester/seed-data/authored/admin__uncovered-admin-pages.js +235 -0
  63. package/dist/features/tester/seed-data/authored/admin__users-trust.d.ts +2 -0
  64. package/dist/features/tester/seed-data/authored/admin__users-trust.js +569 -0
  65. package/dist/features/tester/seed-data/authored/buying__bidding.d.ts +2 -0
  66. package/dist/features/tester/seed-data/authored/buying__bidding.js +417 -0
  67. package/dist/features/tester/seed-data/authored/buying__browsing-search.d.ts +2 -0
  68. package/dist/features/tester/seed-data/authored/buying__browsing-search.js +653 -0
  69. package/dist/features/tester/seed-data/authored/buying__buying-checkout.d.ts +2 -0
  70. package/dist/features/tester/seed-data/authored/buying__buying-checkout.js +533 -0
  71. package/dist/features/tester/seed-data/authored/buying__buying-coupons.d.ts +2 -0
  72. package/dist/features/tester/seed-data/authored/buying__buying-coupons.js +379 -0
  73. package/dist/features/tester/seed-data/authored/buying__cart.d.ts +2 -0
  74. package/dist/features/tester/seed-data/authored/buying__cart.js +1171 -0
  75. package/dist/features/tester/seed-data/authored/buying__image-tile-layout.d.ts +2 -0
  76. package/dist/features/tester/seed-data/authored/buying__image-tile-layout.js +140 -0
  77. package/dist/features/tester/seed-data/authored/buying__my-orders.d.ts +2 -0
  78. package/dist/features/tester/seed-data/authored/buying__my-orders.js +257 -0
  79. package/dist/features/tester/seed-data/authored/buying__offers.d.ts +2 -0
  80. package/dist/features/tester/seed-data/authored/buying__offers.js +1111 -0
  81. package/dist/features/tester/seed-data/authored/buying__order-status-lifecycle.d.ts +2 -0
  82. package/dist/features/tester/seed-data/authored/buying__order-status-lifecycle.js +252 -0
  83. package/dist/features/tester/seed-data/authored/buying__product-detail.d.ts +2 -0
  84. package/dist/features/tester/seed-data/authored/buying__product-detail.js +387 -0
  85. package/dist/features/tester/seed-data/authored/buying__return-request.d.ts +2 -0
  86. package/dist/features/tester/seed-data/authored/buying__return-request.js +152 -0
  87. package/dist/features/tester/seed-data/authored/buying__reviews-pagination.d.ts +2 -0
  88. package/dist/features/tester/seed-data/authored/buying__reviews-pagination.js +242 -0
  89. package/dist/features/tester/seed-data/authored/buying__reviews.d.ts +2 -0
  90. package/dist/features/tester/seed-data/authored/buying__reviews.js +113 -0
  91. package/dist/features/tester/seed-data/authored/buying__user-dashboard-extras.d.ts +2 -0
  92. package/dist/features/tester/seed-data/authored/buying__user-dashboard-extras.js +283 -0
  93. package/dist/features/tester/seed-data/authored/buying__user-dashboard-navigation.d.ts +2 -0
  94. package/dist/features/tester/seed-data/authored/buying__user-dashboard-navigation.js +167 -0
  95. package/dist/features/tester/seed-data/authored/buying__user-uncovered-pages.d.ts +2 -0
  96. package/dist/features/tester/seed-data/authored/buying__user-uncovered-pages.js +90 -0
  97. package/dist/features/tester/seed-data/authored/buying__wishlist-history.d.ts +2 -0
  98. package/dist/features/tester/seed-data/authored/buying__wishlist-history.js +344 -0
  99. package/dist/features/tester/seed-data/authored/community-support__public-profile.d.ts +2 -0
  100. package/dist/features/tester/seed-data/authored/community-support__public-profile.js +53 -0
  101. package/dist/features/tester/seed-data/authored/community-support__support-tickets.d.ts +2 -0
  102. package/dist/features/tester/seed-data/authored/community-support__support-tickets.js +76 -0
  103. package/dist/features/tester/seed-data/authored/content-discovery__blog.d.ts +2 -0
  104. package/dist/features/tester/seed-data/authored/content-discovery__blog.js +93 -0
  105. package/dist/features/tester/seed-data/authored/content-discovery__category-brand-relations.d.ts +2 -0
  106. package/dist/features/tester/seed-data/authored/content-discovery__category-brand-relations.js +149 -0
  107. package/dist/features/tester/seed-data/authored/content-discovery__coupons.d.ts +2 -0
  108. package/dist/features/tester/seed-data/authored/content-discovery__coupons.js +121 -0
  109. package/dist/features/tester/seed-data/authored/content-discovery__event-participation.d.ts +2 -0
  110. package/dist/features/tester/seed-data/authored/content-discovery__event-participation.js +207 -0
  111. package/dist/features/tester/seed-data/authored/content-discovery__events.d.ts +2 -0
  112. package/dist/features/tester/seed-data/authored/content-discovery__events.js +318 -0
  113. package/dist/features/tester/seed-data/authored/content-discovery__faq-help.d.ts +2 -0
  114. package/dist/features/tester/seed-data/authored/content-discovery__faq-help.js +65 -0
  115. package/dist/features/tester/seed-data/authored/content-discovery__notifications.d.ts +2 -0
  116. package/dist/features/tester/seed-data/authored/content-discovery__notifications.js +147 -0
  117. package/dist/features/tester/seed-data/authored/content-discovery__search.d.ts +2 -0
  118. package/dist/features/tester/seed-data/authored/content-discovery__search.js +332 -0
  119. package/dist/features/tester/seed-data/authored/cta-layout__checkout-bottom-bar.d.ts +2 -0
  120. package/dist/features/tester/seed-data/authored/cta-layout__checkout-bottom-bar.js +53 -0
  121. package/dist/features/tester/seed-data/authored/cta-layout__dialog-footers.d.ts +2 -0
  122. package/dist/features/tester/seed-data/authored/cta-layout__dialog-footers.js +52 -0
  123. package/dist/features/tester/seed-data/authored/cta-layout__editor-action-bar.d.ts +2 -0
  124. package/dist/features/tester/seed-data/authored/cta-layout__editor-action-bar.js +35 -0
  125. package/dist/features/tester/seed-data/authored/cta-layout__navbar-ctas.d.ts +2 -0
  126. package/dist/features/tester/seed-data/authored/cta-layout__navbar-ctas.js +141 -0
  127. package/dist/features/tester/seed-data/authored/cta-layout__product-bottom-bar.d.ts +2 -0
  128. package/dist/features/tester/seed-data/authored/cta-layout__product-bottom-bar.js +35 -0
  129. package/dist/features/tester/seed-data/authored/design-ux__back-to-top-button.d.ts +2 -0
  130. package/dist/features/tester/seed-data/authored/design-ux__back-to-top-button.js +95 -0
  131. package/dist/features/tester/seed-data/authored/design-ux__carousel-arrow-bounds.d.ts +2 -0
  132. package/dist/features/tester/seed-data/authored/design-ux__carousel-arrow-bounds.js +191 -0
  133. package/dist/features/tester/seed-data/authored/design-ux__dashboard-layout.d.ts +2 -0
  134. package/dist/features/tester/seed-data/authored/design-ux__dashboard-layout.js +158 -0
  135. package/dist/features/tester/seed-data/authored/design-ux__footer-theme.d.ts +2 -0
  136. package/dist/features/tester/seed-data/authored/design-ux__footer-theme.js +106 -0
  137. package/dist/features/tester/seed-data/authored/design-ux__form-validation-errors.d.ts +2 -0
  138. package/dist/features/tester/seed-data/authored/design-ux__form-validation-errors.js +88 -0
  139. package/dist/features/tester/seed-data/authored/design-ux__general-design.d.ts +2 -0
  140. package/dist/features/tester/seed-data/authored/design-ux__general-design.js +204 -0
  141. package/dist/features/tester/seed-data/authored/design-ux__hand-mode-layout.d.ts +2 -0
  142. package/dist/features/tester/seed-data/authored/design-ux__hand-mode-layout.js +301 -0
  143. package/dist/features/tester/seed-data/authored/design-ux__homepage-carousels.d.ts +2 -0
  144. package/dist/features/tester/seed-data/authored/design-ux__homepage-carousels.js +407 -0
  145. package/dist/features/tester/seed-data/authored/design-ux__status-badge-legibility.d.ts +2 -0
  146. package/dist/features/tester/seed-data/authored/design-ux__status-badge-legibility.js +214 -0
  147. package/dist/features/tester/seed-data/authored/design-ux__sticky-cta-bar.d.ts +2 -0
  148. package/dist/features/tester/seed-data/authored/design-ux__sticky-cta-bar.js +275 -0
  149. package/dist/features/tester/seed-data/authored/index.d.ts +2 -0
  150. package/dist/features/tester/seed-data/authored/index.js +237 -0
  151. package/dist/features/tester/seed-data/authored/page-wiring__data-loss.d.ts +2 -0
  152. package/dist/features/tester/seed-data/authored/page-wiring__data-loss.js +102 -0
  153. package/dist/features/tester/seed-data/authored/page-wiring__detail-pages.d.ts +2 -0
  154. package/dist/features/tester/seed-data/authored/page-wiring__detail-pages.js +50 -0
  155. package/dist/features/tester/seed-data/authored/page-wiring__drawer-pages.d.ts +2 -0
  156. package/dist/features/tester/seed-data/authored/page-wiring__drawer-pages.js +66 -0
  157. package/dist/features/tester/seed-data/authored/page-wiring__reachability.d.ts +2 -0
  158. package/dist/features/tester/seed-data/authored/page-wiring__reachability.js +115 -0
  159. package/dist/features/tester/seed-data/authored/public-pages__auth-error-pages.d.ts +2 -0
  160. package/dist/features/tester/seed-data/authored/public-pages__auth-error-pages.js +136 -0
  161. package/dist/features/tester/seed-data/authored/public-pages__bug-hunters.d.ts +2 -0
  162. package/dist/features/tester/seed-data/authored/public-pages__bug-hunters.js +69 -0
  163. package/dist/features/tester/seed-data/authored/public-pages__core-listing-pages.d.ts +2 -0
  164. package/dist/features/tester/seed-data/authored/public-pages__core-listing-pages.js +263 -0
  165. package/dist/features/tester/seed-data/authored/public-pages__help-how-it-works.d.ts +2 -0
  166. package/dist/features/tester/seed-data/authored/public-pages__help-how-it-works.js +102 -0
  167. package/dist/features/tester/seed-data/authored/public-pages__help-scams-guides-subpages.d.ts +2 -0
  168. package/dist/features/tester/seed-data/authored/public-pages__help-scams-guides-subpages.js +234 -0
  169. package/dist/features/tester/seed-data/authored/public-pages__legal-policy-pages.d.ts +2 -0
  170. package/dist/features/tester/seed-data/authored/public-pages__legal-policy-pages.js +126 -0
  171. package/dist/features/tester/seed-data/authored/public-pages__stores-sellers-directories.d.ts +2 -0
  172. package/dist/features/tester/seed-data/authored/public-pages__stores-sellers-directories.js +255 -0
  173. package/dist/features/tester/seed-data/authored/search-and-nav__employee-permissions.d.ts +2 -0
  174. package/dist/features/tester/seed-data/authored/search-and-nav__employee-permissions.js +59 -0
  175. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.d.ts +2 -0
  176. package/dist/features/tester/seed-data/authored/search-and-nav__header-search.js +88 -0
  177. package/dist/features/tester/seed-data/authored/search-and-nav__settings-deep-links.d.ts +2 -0
  178. package/dist/features/tester/seed-data/authored/search-and-nav__settings-deep-links.js +51 -0
  179. package/dist/features/tester/seed-data/authored/search-and-nav__sidebar-search.d.ts +2 -0
  180. package/dist/features/tester/seed-data/authored/search-and-nav__sidebar-search.js +35 -0
  181. package/dist/features/tester/seed-data/authored/selling__become-seller.d.ts +2 -0
  182. package/dist/features/tester/seed-data/authored/selling__become-seller.js +94 -0
  183. package/dist/features/tester/seed-data/authored/selling__final-sale-authoring.d.ts +2 -0
  184. package/dist/features/tester/seed-data/authored/selling__final-sale-authoring.js +107 -0
  185. package/dist/features/tester/seed-data/authored/selling__listing-a-product.d.ts +2 -0
  186. package/dist/features/tester/seed-data/authored/selling__listing-a-product.js +285 -0
  187. package/dist/features/tester/seed-data/authored/selling__listing-lifecycle.d.ts +2 -0
  188. package/dist/features/tester/seed-data/authored/selling__listing-lifecycle.js +326 -0
  189. package/dist/features/tester/seed-data/authored/selling__listing-type-fields-roundtrip.d.ts +2 -0
  190. package/dist/features/tester/seed-data/authored/selling__listing-type-fields-roundtrip.js +136 -0
  191. package/dist/features/tester/seed-data/authored/selling__media-limits.d.ts +2 -0
  192. package/dist/features/tester/seed-data/authored/selling__media-limits.js +128 -0
  193. package/dist/features/tester/seed-data/authored/selling__sectionised-forms.d.ts +2 -0
  194. package/dist/features/tester/seed-data/authored/selling__sectionised-forms.js +167 -0
  195. package/dist/features/tester/seed-data/authored/selling__seller-analytics-payouts.d.ts +2 -0
  196. package/dist/features/tester/seed-data/authored/selling__seller-analytics-payouts.js +117 -0
  197. package/dist/features/tester/seed-data/authored/selling__seller-bids-bundles-filters.d.ts +2 -0
  198. package/dist/features/tester/seed-data/authored/selling__seller-bids-bundles-filters.js +88 -0
  199. package/dist/features/tester/seed-data/authored/selling__seller-catalog-org.d.ts +2 -0
  200. package/dist/features/tester/seed-data/authored/selling__seller-catalog-org.js +151 -0
  201. package/dist/features/tester/seed-data/authored/selling__seller-custom-brands.d.ts +2 -0
  202. package/dist/features/tester/seed-data/authored/selling__seller-custom-brands.js +105 -0
  203. package/dist/features/tester/seed-data/authored/selling__seller-guide.d.ts +2 -0
  204. package/dist/features/tester/seed-data/authored/selling__seller-guide.js +33 -0
  205. package/dist/features/tester/seed-data/authored/selling__seller-listing-types.d.ts +2 -0
  206. package/dist/features/tester/seed-data/authored/selling__seller-listing-types.js +347 -0
  207. package/dist/features/tester/seed-data/authored/selling__seller-marketing-extras.d.ts +2 -0
  208. package/dist/features/tester/seed-data/authored/selling__seller-marketing-extras.js +166 -0
  209. package/dist/features/tester/seed-data/authored/selling__seller-ops-comms.d.ts +2 -0
  210. package/dist/features/tester/seed-data/authored/selling__seller-ops-comms.js +89 -0
  211. package/dist/features/tester/seed-data/authored/selling__seller-orders.d.ts +2 -0
  212. package/dist/features/tester/seed-data/authored/selling__seller-orders.js +195 -0
  213. package/dist/features/tester/seed-data/authored/selling__seller-shipping-payouts-setup.d.ts +2 -0
  214. package/dist/features/tester/seed-data/authored/selling__seller-shipping-payouts-setup.js +180 -0
  215. package/dist/features/tester/seed-data/authored/selling__store-dashboard-navigation.d.ts +2 -0
  216. package/dist/features/tester/seed-data/authored/selling__store-dashboard-navigation.js +164 -0
  217. package/dist/features/tester/seed-data/authored/selling__store-uncovered-pages.d.ts +2 -0
  218. package/dist/features/tester/seed-data/authored/selling__store-uncovered-pages.js +116 -0
  219. package/dist/features/tester/seed-data/authored/seo__canonical-and-host.d.ts +2 -0
  220. package/dist/features/tester/seed-data/authored/seo__canonical-and-host.js +111 -0
  221. package/dist/features/tester/seed-data/authored/seo__og-images.d.ts +2 -0
  222. package/dist/features/tester/seed-data/authored/seo__og-images.js +91 -0
  223. package/dist/features/tester/seed-data/authored/seo__page-metadata.d.ts +2 -0
  224. package/dist/features/tester/seed-data/authored/seo__page-metadata.js +122 -0
  225. package/dist/features/tester/seed-data/authored/seo__sitemap-and-robots.d.ts +2 -0
  226. package/dist/features/tester/seed-data/authored/seo__sitemap-and-robots.js +105 -0
  227. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +744 -1
  228. package/dist/seed/carousel-slides-seed-data.js +1 -1
  229. package/dist/seed/products-standard-seed-data.js +2 -2
  230. package/dist/seed/reviews-seed-data.js +6 -1
  231. package/package.json +1 -1
  232. package/scripts/seed-cli.mjs +6 -0
@@ -0,0 +1,569 @@
1
+ /*
2
+ * WHY: Authored six-part procedures for the admin/users-trust checklist page.
3
+ * WHAT: 33 case(s), keyed by full checklist id.
4
+ *
5
+ * Written by hand, case by case, against the label each one states. There is no
6
+ * generator: the authoring scripts were deleted once it was clear they were
7
+ * scaffolding around work that is simply writing.
8
+ *
9
+ * 🛑 TWO THEMES RUN THROUGH THIS PAGE.
10
+ *
11
+ * First: an admin must be able to READ a record before acting on it. Moderation
12
+ * queues, reports, item requests and catalogue approvals all shipped as rows
13
+ * offering Approve and Reject over content that was never rendered — a decision
14
+ * made blind, and it looks complete because the buttons work.
15
+ *
16
+ * Second: a list serializer that omits a field the editor also sends back is how
17
+ * saving one thing silently resets another. The user editor did exactly that with
18
+ * the tester flags: the list omitted them, the editor seeded them as undefined,
19
+ * and the save handler sent that default unconditionally — so editing anything
20
+ * else stripped a real tester's access.
21
+ *
22
+ * @tag domain:tester
23
+ * @tag layer:seed
24
+ * @tag pattern:none
25
+ * @tag access:server-only
26
+ * @tag consumers:seed-data/authored/index.ts
27
+ * @tag sideEffects:none
28
+ */
29
+ export const authored = {
30
+ "checklist-admin-users-trust-users-role-change": {
31
+ roles: ["admin"],
32
+ startPage: "/admin/users",
33
+ steps: [
34
+ "Sign in as admin@letitrip.in / TempPass123!.",
35
+ "Open /admin/users and find karthik.new@gmail.com.",
36
+ "Open the editor and write down every field, including the tester flags.",
37
+ "Change ONLY the role and save.",
38
+ "RELOAD the editor and compare every field against what was written down.",
39
+ "Check the tester flags specifically.",
40
+ "Open /admin/audit-log and read the newest entry.",
41
+ "Set the role back to what it was.",
42
+ ],
43
+ inputs: { user: "karthik.new@gmail.com" },
44
+ expectedBehaviour: "A role change is recorded in the audit log with the actor, the target and the before-and-after values — that is one of the eight instrumented privileged actions. It must also leave every other field alone: the list serializer once omitted the tester flags, so the editor seeded them as undefined and the save sent that default back, stripping a real tester's access as a side effect of an unrelated edit.",
45
+ expectedUiState: "After the reload only the role differs. The tester flags hold their previous values. The audit log's newest entry names the role change, the acting admin and the target.",
46
+ expectedData: { unintendedFieldChanges: 0 },
47
+ endResult: "The role is restored. Re-read the flags after the reload, not just the field that was edited.",
48
+ },
49
+ "checklist-admin-users-trust-admin-user-detail-enriched": {
50
+ roles: ["admin"],
51
+ startPage: "/admin/users",
52
+ steps: [
53
+ "Sign in as admin@letitrip.in / TempPass123!.",
54
+ "Open /admin/users and open a buyer with orders and a wishlist.",
55
+ "Read every section of their detail page.",
56
+ "Check their orders, addresses, wishlist and history are reachable from here.",
57
+ "Read how their email and phone are displayed.",
58
+ "Read whether their session list and any ban state are shown.",
59
+ "Search the page source for the full unmasked email.",
60
+ ],
61
+ expectedBehaviour: "The user page is where an admin assembles a picture of one person, so the related records are reachable from it — which is also why two other listings deliberately route their rows here rather than to a detail of their own. Email and phone are PII-encrypted at rest, so how much is decrypted and displayed is a deliberate choice worth recording.",
62
+ expectedUiState: "Orders, addresses, wishlist and history are all reachable. Ban state and sessions are shown. Record exactly how the email and phone appear, and whether the full email is present in the page source even if masked on screen.",
63
+ endResult: "Read-only; nothing persists.",
64
+ },
65
+ "checklist-admin-users-trust-admin-delete-user-complete": {
66
+ roles: ["admin"],
67
+ startPage: "/admin/users",
68
+ steps: [
69
+ "Sign in as admin@letitrip.in / TempPass123!.",
70
+ "Open /admin/users and locate the delete action on a row.",
71
+ "Read the confirmation it opens WITHOUT confirming it.",
72
+ "Check whether it names what will be removed and what will be kept.",
73
+ "Check whether it warns that the Firebase Auth record is also destroyed.",
74
+ "CANCEL the dialog.",
75
+ "RELOAD and confirm the user is untouched.",
76
+ ],
77
+ expectedBehaviour: "Deleting a user is irreversible and reaches beyond Firestore into the Auth record. A destructive action of that reach must carry a confirmation naming the consequences — the users collection is the one tier a tester run never wipes precisely because it cannot be rebuilt from seed data.",
78
+ expectedUiState: "The confirmation names what is destroyed rather than asking a generic 'Are you sure?'. Cancelling leaves the user present after a reload.",
79
+ endResult: "No user is deleted. CANCEL rather than confirm — a real signup deleted here cannot be restored.",
80
+ },
81
+ "checklist-admin-users-trust-roles-crud": {
82
+ roles: ["admin"],
83
+ startPage: "/admin/team",
84
+ steps: [
85
+ "Sign in as admin@letitrip.in / TempPass123!.",
86
+ "Open the roles or permissions surface and read every role and its permissions.",
87
+ "Read whether a permissions catalogue page exists and is reachable from the sidebar.",
88
+ "Create a role named 'QA Role users-trust' with two permissions and save.",
89
+ "RELOAD and read its permissions.",
90
+ "Edit it to add a third, save, RELOAD, and check the first two are still there.",
91
+ "Delete the role and confirm it is gone.",
92
+ ],
93
+ inputs: { name: "QA Role users-trust" },
94
+ expectedBehaviour: "Roles carry permission sets and an edit adds rather than replaces. Permissions are keyed on nav item ids, and the filter that applies them short-circuits when an item has no id — which is how every requiredPermission in the config was decorative while looking configured.",
95
+ expectedUiState: "After each reload the role holds every permission assigned. The third addition does not drop the first two. Any permissions catalogue page linked from the nav actually exists.",
96
+ endResult: "The role is deleted by the final step.",
97
+ },
98
+ "checklist-admin-users-trust-sessions-revoke": {
99
+ roles: ["admin", "buyer"],
100
+ startPage: "/admin/sessions",
101
+ steps: [
102
+ "In window A, sign in as karthik.new@gmail.com / TempPass123! and open /user.",
103
+ "In window B, sign in as admin@letitrip.in / TempPass123! and open the admin sessions listing.",
104
+ "Find that user's active session and read what the row shows — device, last activity, location.",
105
+ "Read whether the IP address is shown in full or masked.",
106
+ "Revoke the session.",
107
+ "Return to window A and navigate to another /user page without reloading.",
108
+ "Then reload window A and read what happens.",
109
+ ],
110
+ inputs: { user: "karthik.new@gmail.com" },
111
+ expectedBehaviour: "Revoking ends the session. The IP is stored masked and must never be returned to a client in full — it is one of the few network identifiers the product holds. The client re-reads its session state on a periodic ping rather than every navigation, so a revoked session may survive a client-side navigation and must not survive a reload.",
112
+ expectedUiState: "The row shows device, last activity and a MASKED IP. After revocation window A is signed out on reload at the latest. Record how long it took — an immediate effect is better, a reload-scoped one is expected, and no effect at all is the failure.",
113
+ endResult: "The session is revoked. Sign the account back in afterwards, since other cases use it.",
114
+ },
115
+ "checklist-admin-users-trust-scammers-registry-admin": {
116
+ roles: ["admin"],
117
+ startPage: "/admin/scammers",
118
+ steps: [
119
+ "Sign in as admin@letitrip.in / TempPass123!.",
120
+ "Open /admin/scammers and read every column.",
121
+ "Read every status filter offered and select each, noting any that returns nothing.",
122
+ "For each empty filter, check the unfiltered list for rows of that status.",
123
+ "Create a profile named 'QA Scammer users-trust' with a scam type and a description, and save.",
124
+ "RELOAD and read every field.",
125
+ "Edit ONLY the description, save, RELOAD, and check the status and type are unchanged.",
126
+ "Delete the profile.",
127
+ ],
128
+ inputs: { name: "QA Scammer users-trust" },
129
+ expectedBehaviour: "Every status chip names a value profiles actually hold — the canonical field-name constants and the feature's own type file have disagreed before, one missing a real status the other had, so the chips must be read against the real list. An edit is recorded with a history entry; this route once bypassed that entirely.",
130
+ expectedUiState: "Every status filter returns its own rows or is empty with none unfiltered either. After the description edit the status and type are unchanged and a history entry records the change.",
131
+ endResult: "The profile is deleted by the final step.",
132
+ },
133
+ "checklist-admin-users-trust-banned-addresses-admin": {
134
+ roles: ["admin"],
135
+ startPage: "/admin/addresses",
136
+ steps: [
137
+ "Sign in as admin@letitrip.in / TempPass123!.",
138
+ "Open the banned-addresses surface and read every column.",
139
+ "Check each row shows the address, who banned it, when, and why.",
140
+ "Read whether an unban request from the owner is visible on the row.",
141
+ "Open one and read the requester's full note before deciding anything.",
142
+ "Read the actions offered and check a view exists alongside them.",
143
+ "Use every filter offered and confirm each changes the rows.",
144
+ ],
145
+ expectedBehaviour: "A ban carries its reason and an unban request carries its note — the note is the ENTIRE case a reviewer reads, which is why the buyer-side form enforces a twenty-character minimum. A row offering Approve and Reject without showing that note is a decision made blind.",
146
+ expectedUiState: "Rows show the address, the actor, the time and the reason. The requester's note is readable before any decision. Filters change the rows.",
147
+ endResult: "Read-only; decide nothing.",
148
+ },
149
+ "checklist-admin-users-trust-address-clusters-admin": {
150
+ roles: ["admin"],
151
+ startPage: "/admin/addresses",
152
+ steps: [
153
+ "Sign in as admin@letitrip.in / TempPass123!.",
154
+ "Open the address clusters surface and read what a cluster row represents.",
155
+ "Check each row states how many accounts share the address and names them.",
156
+ "Open a cluster and read the accounts it groups.",
157
+ "Read whether the shared address itself is shown in full or masked.",
158
+ "Read the actions offered and check a view exists alongside them.",
159
+ "Use every filter offered and confirm each changes the rows.",
160
+ ],
161
+ expectedBehaviour: "A cluster is the fraud signal — several accounts sharing one delivery address. The row has to name the accounts, because acting on a cluster without seeing who is in it is the same blind decision as approving a submission whose contents were never rendered.",
162
+ expectedUiState: "Rows state the account count and the cluster opens to name them. Address detail is shown only as far as the moderation task needs. A cluster row with a count and no way to see the accounts is the failure.",
163
+ endResult: "Read-only; take no action.",
164
+ },
165
+ "checklist-admin-users-trust-moderation-queue-admin": {
166
+ roles: ["admin"],
167
+ startPage: "/admin/moderation",
168
+ steps: [
169
+ "Sign in as admin@letitrip.in / TempPass123!.",
170
+ "Open the moderation queue and read every row.",
171
+ "Check each row identifies what is being moderated and shows enough to judge it.",
172
+ "Open one item and read its full content — text, images, whatever was submitted.",
173
+ "Return to the list and check the same is reachable from the row itself.",
174
+ "Read every status filter and select each, noting any that returns nothing.",
175
+ "Read the ordering and check the oldest pending item is first.",
176
+ ],
177
+ expectedBehaviour: "An item's content is readable before a decision. This queue and the report, item-request and catalogue-approval surfaces all shipped as rows offering Approve and Reject over content that was never rendered — the buttons worked, which is why it looked finished.",
178
+ expectedUiState: "Every row shows or reaches the content being judged. Filters return their own rows. The oldest pending item is first, since a queue ordered newest-first buries the items that have waited longest.",
179
+ endResult: "Read-only; decide nothing.",
180
+ },
181
+ "checklist-admin-users-trust-moderation-reject-requires-reason": {
182
+ roles: ["admin"],
183
+ startPage: "/admin/moderation",
184
+ steps: [
185
+ "Sign in as admin@letitrip.in / TempPass123!.",
186
+ "Open the moderation queue and open an item.",
187
+ "Read its content, then choose Reject.",
188
+ "Submit with the reason box empty and read what happens.",
189
+ "Type 'Too short' and submit, reading what happens.",
190
+ "Type a full sentence explaining the rejection and submit.",
191
+ "RELOAD and read the item's status and the recorded reason.",
192
+ ],
193
+ expectedBehaviour: "A rejection carries a reason, enforced on the field rather than by a disabled button. The reason is what the submitter is told and what a later reviewer reads — a rejection with no reason is an outcome nobody can appeal or learn from.",
194
+ expectedUiState: "The empty submit puts an error on the reason field rather than silently doing nothing. The full sentence is accepted. After the reload the item is rejected and the reason is stored against it.",
195
+ endResult: "One item is rejected with a reason. A disabled button that does nothing when pressed is the failure — the admin cannot tell it from a broken page.",
196
+ },
197
+ "checklist-admin-users-trust-moderation-reject-keeps-note-on-failure": {
198
+ roles: ["admin"],
199
+ startPage: "/admin/moderation",
200
+ steps: [
201
+ "Sign in as admin@letitrip.in / TempPass123!.",
202
+ "Open a moderation item and choose Reject.",
203
+ "Type a long, carefully worded reason into the box.",
204
+ "Open browser DevTools and set the network to offline.",
205
+ "Submit and read what happens.",
206
+ "Set the network back online.",
207
+ "Read whether the typed reason is still in the box.",
208
+ "Submit again and confirm it succeeds.",
209
+ ],
210
+ expectedBehaviour: "A failed submit keeps the typed text. Clearing the form on failure destroys work the admin cannot recover, and a long rejection reason is exactly the kind of text nobody wants to write twice.",
211
+ expectedUiState: "The offline submit shows a readable error rather than a stack trace. The reason is still in the box afterwards, character for character. The retry succeeds.",
212
+ endResult: "The item is rejected on the retry. An emptied box after a failed submit is the failure.",
213
+ },
214
+ "checklist-admin-users-trust-support-tickets-triage-admin": {
215
+ roles: ["admin"],
216
+ startPage: "/admin/support",
217
+ steps: [
218
+ "Sign in as admin@letitrip.in / TempPass123!.",
219
+ "Open the admin support tickets surface and read every column.",
220
+ "Read every status filter and select each, noting any that returns nothing.",
221
+ "Open a ticket and read the full message thread.",
222
+ "Reply to it and change its status in the same action.",
223
+ "RELOAD and read the thread, the status and the history entries.",
224
+ "Reply again WITHOUT changing the status and read the history.",
225
+ ],
226
+ expectedBehaviour: "A reply appends to the ticket's thread and a status change is recorded with an actor. An ordinary reply that carries no status change costs one write and no read — the ticket is only re-read when a status accompanies the message, which is why the second reply is worth making separately.",
227
+ expectedUiState: "The thread grows by one entry per reply, in order, with the earlier messages unchanged. The status change is recorded in history with an actor and a time. The status-free reply adds a message without inventing a status transition.",
228
+ endResult: "The ticket carries both replies.",
229
+ },
230
+ "checklist-admin-users-trust-item-requests-admin": {
231
+ roles: ["admin"],
232
+ startPage: "/admin/item-requests",
233
+ steps: [
234
+ "Sign in as admin@letitrip.in / TempPass123!.",
235
+ "Open the item-requests surface and read every row.",
236
+ "Check each row shows the requested item's title and description rather than only a requester.",
237
+ "Open one and read the full request before acting.",
238
+ "Read the actions offered and check a view exists alongside them.",
239
+ "Read every status filter and select each.",
240
+ "Search zzzznope and read the count.",
241
+ ],
242
+ inputs: { nonsenseQuery: "zzzznope" },
243
+ expectedBehaviour: "A request is readable before it is actioned. This surface is one of the four that offered decisions over content the row never rendered — and an item request is nothing BUT its text, so a row without it shows the admin nothing at all.",
244
+ expectedUiState: "Rows show the requested title and enough description to judge, and open to the full text. Filters return their own rows and 'zzzznope' returns none.",
245
+ expectedData: { nonsenseResultCount: 0 },
246
+ endResult: "Read-only; decide nothing.",
247
+ },
248
+ "checklist-admin-users-trust-item-request-requires-title-and-description": {
249
+ roles: ["buyer"],
250
+ startPage: "/user",
251
+ steps: [
252
+ "Sign in as rehan.sheikh@gmail.com / TempPass123!.",
253
+ "Open the item-request form from the buyer side.",
254
+ "Submit it completely empty and read where the errors appear.",
255
+ "Type a title only and submit, reading what happens.",
256
+ "Type a one-word description and submit, reading what happens.",
257
+ "Type 'QA Item Request users-trust' as the title and a full sentence as the description, then submit.",
258
+ "RELOAD and confirm the request was created.",
259
+ ],
260
+ inputs: { title: "QA Item Request users-trust" },
261
+ expectedBehaviour: "Both a title and a real description are required, enforced on their own fields before any request is sent. A request with no description is one an admin cannot act on, so accepting it just moves the dead end downstream.",
262
+ expectedUiState: "The empty submit marks both fields individually rather than showing one banner. The title-only submit marks the description. The complete submission is accepted and survives a reload.",
263
+ endResult: "One request exists. It is the fixture the admin item-requests case reads.",
264
+ },
265
+ "checklist-admin-users-trust-reports-admin": {
266
+ roles: ["admin"],
267
+ startPage: "/admin/reports",
268
+ steps: [
269
+ "Sign in as admin@letitrip.in / TempPass123!.",
270
+ "Open the reports surface and read every row.",
271
+ "Check each row names what was reported and by whom, and shows the reporter's stated detail.",
272
+ "Open one and read the full report before acting.",
273
+ "Read every status filter and select each, noting any that returns nothing.",
274
+ "For each empty filter, check the unfiltered list for rows of that status.",
275
+ "Read the actions offered and check a view exists alongside them.",
276
+ ],
277
+ expectedBehaviour: "A report is readable before it is dismissed or closed. Its status values must be ones reports actually hold — a chip naming a value the documents never carry matches nothing forever and looks like a category with no reports.",
278
+ expectedUiState: "Rows name the target, the reporter and the reason, and open to the full detail. Every filter returns its own rows or is empty with none unfiltered either.",
279
+ endResult: "Read-only; decide nothing.",
280
+ },
281
+ "checklist-admin-users-trust-report-submit-requires-detail": {
282
+ roles: ["buyer"],
283
+ startPage: "/products/product-beyblade-burst-valkyrie",
284
+ steps: [
285
+ "Sign in as rehan.sheikh@gmail.com / TempPass123!.",
286
+ "Open /products/product-beyblade-burst-valkyrie and find the report control.",
287
+ "Submit the report with no detail and read where any error appears.",
288
+ "Type a single word and submit, reading what happens.",
289
+ "Type 'QA Report users-trust — listing description does not match the photos.' and submit.",
290
+ "Read the confirmation.",
291
+ ],
292
+ inputs: { detail: "QA Report users-trust — listing description does not match the photos." },
293
+ expectedBehaviour: "A report requires enough detail to act on, enforced on the field. A report with no detail is one a moderator cannot judge, so accepting it fills the queue with items that can only be dismissed.",
294
+ expectedUiState: "The empty and one-word submissions put an error on the detail field. The full sentence is accepted with a confirmation. A disabled submit button that says nothing is the failure.",
295
+ endResult: "One report exists. It is the fixture the admin reports cases read.",
296
+ },
297
+ "checklist-admin-users-trust-report-dismiss-asks-why": {
298
+ roles: ["admin"],
299
+ startPage: "/admin/reports",
300
+ steps: [
301
+ "Sign in as admin@letitrip.in / TempPass123!.",
302
+ "Open the reports surface and open the report created by the buyer case.",
303
+ "Read its full detail, then choose Dismiss.",
304
+ "Submit with the reason empty and read what happens.",
305
+ "Type 'QA Dismissal users-trust — reviewed, no policy breach.' and submit.",
306
+ "RELOAD and read the report's status and the recorded reason.",
307
+ ],
308
+ inputs: { reason: "QA Dismissal users-trust — reviewed, no policy breach." },
309
+ expectedBehaviour: "A dismissal carries a reason. Without one there is no record of why a report was rejected, and the next moderator reading the same target has nothing to go on — the reason is the only artefact a dismissal leaves.",
310
+ expectedUiState: "The empty submit is refused on the reason field. After the reload the report reads as dismissed and the reason is stored and readable.",
311
+ endResult: "The report is dismissed with a reason recorded.",
312
+ },
313
+ "checklist-admin-users-trust-report-close-stores-a-real-date": {
314
+ roles: ["admin"],
315
+ startPage: "/admin/reports",
316
+ steps: [
317
+ "Sign in as admin@letitrip.in / TempPass123!.",
318
+ "Open the reports surface and open an open report.",
319
+ "Note the current date and time.",
320
+ "Close the report with a resolution note.",
321
+ "RELOAD and read the closed date shown.",
322
+ "Compare it against the time the action was taken.",
323
+ "Check no other status on the report shows an invented timestamp.",
324
+ ],
325
+ expectedBehaviour: "Closing stores a real timestamp taken at the moment of the action. A status with no recorded date renders an em-dash rather than a fabricated one — never the current time as a stand-in, and never a proxy field such as the record's last-updated value, which means 'last write of any kind' and not 'when this happened'.",
326
+ expectedUiState: "The closed date matches when the action was taken. Statuses with no recorded date show an em-dash rather than a plausible-looking substitute.",
327
+ endResult: "The report is closed with a real date. A fabricated timestamp is worse than a missing one, because it cannot be distinguished from a true one later.",
328
+ },
329
+ "checklist-admin-users-trust-report-status-rejects-unknown-values": {
330
+ roles: ["admin"],
331
+ startPage: "/admin/reports",
332
+ steps: [
333
+ "Sign in as admin@letitrip.in / TempPass123!.",
334
+ "Open the reports surface and read every status the status control offers.",
335
+ "Write the list down.",
336
+ "Select each in turn on a test report and confirm each is accepted.",
337
+ "Open the reports list and read every status filter chip.",
338
+ "Compare the chip list against the status list from the editor.",
339
+ "Note any chip naming a status the editor cannot set, or any status the editor sets that has no chip.",
340
+ ],
341
+ expectedBehaviour: "The statuses a report can be SET to and the statuses it can be FILTERED by are the same list. Where the two are maintained separately they drift — a chip for a status nothing can produce matches nothing forever, and a status with no chip makes those reports unfindable.",
342
+ expectedUiState: "The editor's statuses and the filter chips are the same set, with nothing in one and not the other. A chip returning zero rows for a status the editor can set is the more likely half.",
343
+ endResult: "Read-only apart from any status set on a test report.",
344
+ },
345
+ "checklist-admin-users-trust-catalogue-approvals-admin": {
346
+ roles: ["admin"],
347
+ startPage: "/admin/catalogue-approvals",
348
+ steps: [
349
+ "Sign in as admin@letitrip.in / TempPass123!.",
350
+ "Open the catalogue approvals surface and read every row.",
351
+ "Check each row shows the submitted item's photos, description and price.",
352
+ "Read every status filter and select each.",
353
+ "Open one submission and read everything the user submitted.",
354
+ "Read the actions offered and check a view exists alongside them.",
355
+ ],
356
+ expectedBehaviour: "A submission's photos and details are visible before it is approved. This surface offered Approve and Reject over a user's photos, description and price that were never rendered anywhere — the clearest instance of a decision made blind in the admin panel.",
357
+ expectedUiState: "Rows show or reach the submitted photos and detail. Filters return their own rows. A row with Approve and Reject and no content is the failure this case exists for.",
358
+ endResult: "Read-only; decide nothing.",
359
+ },
360
+ "checklist-admin-users-trust-catalogue-approvals-view-before-deciding": {
361
+ roles: ["admin"],
362
+ startPage: "/admin/catalogue-approvals",
363
+ steps: [
364
+ "Sign in as admin@letitrip.in / TempPass123!.",
365
+ "Open the catalogue approvals surface and find a pending submission.",
366
+ "WITHOUT using Approve or Reject, find a way to open the submission in full.",
367
+ "Read every photo at full size and the complete description.",
368
+ "Read the price the submitter set and any linked marketplace listing.",
369
+ "Return to the list and confirm the same content is reachable from the row.",
370
+ ],
371
+ expectedBehaviour: "The content is reachable without taking a decision. This is the same assertion as the case above stated from the tester's side: if the only way to see the submission is to act on it, the review is theatre.",
372
+ expectedUiState: "The photos open at full size and the description reads in full, all before any action. A submission that can only be seen after approving it is the failure.",
373
+ endResult: "Read-only; take no decision.",
374
+ },
375
+ "checklist-admin-users-trust-payment-methods-clusters-admin": {
376
+ roles: ["admin"],
377
+ startPage: "/admin/payment-methods",
378
+ steps: [
379
+ "Sign in as admin@letitrip.in / TempPass123!.",
380
+ "Open the payment-methods clusters surface and read what a row represents.",
381
+ "Check each row states how many accounts share the instrument and names them.",
382
+ "Read how the payment identifier itself is displayed.",
383
+ "Search the page source for a full card or UPI identifier.",
384
+ "Read the sort dropdown's default and check it is one of the offered options.",
385
+ "Open a row and read the accounts it groups.",
386
+ ],
387
+ expectedBehaviour: "A shared payment instrument is a fraud signal and the row must name the accounts. The identifier is the most sensitive value on this page and must be masked in the payload as well as on screen — a masked display over an unmasked payload is a leak that looks like a fix. This listing has also shipped with a default sort that was not among its own options, opening the dropdown blank.",
388
+ expectedUiState: "Rows state the account count and open to name them. Identifiers are masked, and the full value does not appear in the page source. The sort dropdown opens with a selection that is one of its options.",
389
+ expectedData: { fullIdentifierInSource: 0 },
390
+ endResult: "Read-only; take no action.",
391
+ },
392
+ "checklist-admin-users-trust-listing-form-every-section-reachable": {
393
+ roles: ["admin"],
394
+ startPage: "/admin/products",
395
+ steps: [
396
+ "Sign in as admin@letitrip.in / TempPass123!.",
397
+ "Open a product editor and read every section header.",
398
+ "Expand each in turn and confirm its fields render.",
399
+ "Resize to 390 pixels wide and expand each again.",
400
+ "Check no section is unreachable behind a horizontal scroll or a clipped control.",
401
+ "Open a picker inside the LAST section and check its list is not clipped.",
402
+ ],
403
+ inputs: { mobileWidth: 390 },
404
+ expectedBehaviour: "Every section opens at both widths. A collapsing container needs overflow hidden to animate, and that same rule clips any picker list opened inside it — the options exist and cannot be seen, worst in the last section where there is least room below.",
405
+ expectedUiState: "All sections expand and their fields render at 1280 and at 390. The picker in the last section shows its full list rather than one cut off at the section boundary.",
406
+ endResult: "Read-only; leave the editor without saving.",
407
+ },
408
+ "checklist-admin-users-trust-listing-form-errors-land-on-fields": {
409
+ roles: ["admin"],
410
+ startPage: "/admin/products",
411
+ steps: [
412
+ "Sign in as admin@letitrip.in / TempPass123!.",
413
+ "Open /admin/products and start a new product.",
414
+ "Read the page before typing and note whether any errors are already listed.",
415
+ "Leave required fields empty in two different sections and collapse both.",
416
+ "Attempt to save.",
417
+ "Read the error summary and click an entry belonging to a collapsed section.",
418
+ "Read where the page lands and whether the field is focused and marked.",
419
+ ],
420
+ expectedBehaviour: "The summary appears only after a submit attempt — a form that opens listing every empty required field accuses the user of mistakes before they have typed anything. Clicking an entry expands its section and lands ON the field, focused; landing on the section heading leaves the admin hunting through a dozen fields.",
421
+ expectedUiState: "No errors before the save attempt. Afterwards each entry names its section, and clicking one expands that section with the field focused and marked.",
422
+ expectedData: { errorsBeforeSubmit: 0 },
423
+ endResult: "Nothing is saved; leave the editor.",
424
+ },
425
+ "checklist-admin-users-trust-listing-form-save-draft-anywhere": {
426
+ roles: ["admin"],
427
+ startPage: "/admin/products",
428
+ steps: [
429
+ "Sign in as admin@letitrip.in / TempPass123!.",
430
+ "Open /admin/products and start a new product.",
431
+ "Fill only the title and leave every other required field empty.",
432
+ "Use Save draft from the first section and read what happens.",
433
+ "Expand a later section, fill one field there, and use Save draft again.",
434
+ "RELOAD the draft and read both values.",
435
+ "Delete the draft.",
436
+ ],
437
+ inputs: { title: "QA Product save-draft-anywhere" },
438
+ expectedBehaviour: "A draft saves from anywhere in the form without satisfying the publish rules — that is what makes it a draft. It must also not lose the fields from sections the user has not opened, which is the same partial-population trap that blanks untouched fields on a full save.",
439
+ expectedUiState: "Save draft succeeds from both positions without demanding the missing required fields. After the reload both entered values are present. A draft save that enforces publish validation is the failure.",
440
+ endResult: "The draft is deleted by the final step.",
441
+ },
442
+ "checklist-admin-users-trust-seller-shipping-storefront-sections": {
443
+ roles: ["admin"],
444
+ startPage: "/admin/stores",
445
+ steps: [
446
+ "Sign in as admin@letitrip.in / TempPass123!.",
447
+ "Open /admin/stores and open a store's editor.",
448
+ "Read every section, including shipping and storefront presentation.",
449
+ "Write down every field's value.",
450
+ "Change one storefront field and save.",
451
+ "RELOAD and compare every field, paying attention to verified, featured and the capabilities.",
452
+ "Restore the changed field.",
453
+ ],
454
+ expectedBehaviour: "Editing a storefront field leaves the store's trust flags alone. The list serializer once omitted verified, featured, capabilities and notes, so the editor seeded them as undefined and sent those defaults back on every save — un-verifying the store and resetting its capabilities as a side effect of an unrelated edit.",
455
+ expectedUiState: "After the reload only the storefront field differs. Verified, featured and the capabilities are unchanged. A store that quietly lost its verified badge is the failure, and the save reported success.",
456
+ expectedData: { verifiedPreserved: true },
457
+ endResult: "The field is restored; the store's flags are as they were.",
458
+ },
459
+ "checklist-admin-users-trust-admin-tables-render-badges-not-text": {
460
+ roles: ["admin"],
461
+ startPage: "/admin/orders",
462
+ steps: [
463
+ "Sign in as admin@letitrip.in / TempPass123!.",
464
+ "Open /admin/orders and read the status column.",
465
+ "Check statuses render as coloured badges rather than plain text.",
466
+ "Check different statuses use different colours.",
467
+ "Open /admin/stores, /admin/payouts and /admin/users and read their status columns.",
468
+ "Switch to dark mode and read all four again.",
469
+ ],
470
+ expectedBehaviour: "Status renders as a badge with its own colour so a table can be scanned rather than read word by word. Inline chips take a status tint with matching ink, and both halves invert with the theme — a literal white ink against a tint is invisible in exactly one theme, which is why both are read.",
471
+ expectedUiState: "All four tables show coloured status badges, with distinct statuses in distinct colours, readable in both themes. Plain text, or badges all one colour, are both failures.",
472
+ endResult: "Read-only; return the site to light mode afterwards.",
473
+ },
474
+ "checklist-admin-users-trust-admin-table-readable-on-phone": {
475
+ roles: ["admin"],
476
+ startPage: "/admin/orders",
477
+ steps: [
478
+ "Sign in as admin@letitrip.in / TempPass123!.",
479
+ "Open /admin/orders at 1280 pixels and note how rows are presented.",
480
+ "Resize to 390 pixels and read the same rows.",
481
+ "Try to scroll the page sideways.",
482
+ "Open a row's action menu and check it is fully on screen.",
483
+ "Repeat on /admin/users and /admin/products.",
484
+ ],
485
+ inputs: { desktopWidth: 1280, mobileWidth: 390 },
486
+ expectedBehaviour: "A table becomes cards on a phone rather than a sideways-scrolling table — columns off the right edge are columns nobody reads. Every row action stays reachable in the card form.",
487
+ expectedUiState: "All three listings render as cards at 390 with their key fields, and none scrolls sideways. Row action menus open fully on screen rather than being clipped at the viewport edge.",
488
+ endResult: "Read-only; restore the window width afterwards.",
489
+ },
490
+ "checklist-admin-users-trust-action-buttons-have-icons": {
491
+ roles: ["admin"],
492
+ startPage: "/admin/products",
493
+ steps: [
494
+ "Sign in as admin@letitrip.in / TempPass123!.",
495
+ "Open /admin/products and open a row action menu.",
496
+ "Read every entry and check each carries an icon alongside its label.",
497
+ "Check destructive entries are visually distinguished from the rest.",
498
+ "Compare the icon size against the row height.",
499
+ "Open a bulk action bar by ticking rows and read its buttons the same way.",
500
+ ],
501
+ expectedBehaviour: "Actions come from the shared registry, which carries each one's icon, label and destructive flag — so an entry with no icon is one defined inline, outside the registry, and an inline definition also bypasses permission gating and confirmation copy.",
502
+ expectedUiState: "Every menu and bulk-bar entry has an icon at a size proportionate to its control. Destructive entries are marked as such. An entry with a label and no icon is the tell that it was defined inline.",
503
+ endResult: "Read-only; choose nothing.",
504
+ },
505
+ "checklist-admin-users-trust-sold-flag-badge-readable": {
506
+ roles: ["admin"],
507
+ startPage: "/admin/products",
508
+ steps: [
509
+ "Sign in as admin@letitrip.in / TempPass123!.",
510
+ "Open /admin/products and switch the availability scope to show sold and ended listings.",
511
+ "Find a sold listing and read its badge.",
512
+ "Read the badge against its background.",
513
+ "Switch to dark mode and read it again.",
514
+ "Compare it against an ended auction's badge and a depleted digital-code listing's.",
515
+ ],
516
+ expectedBehaviour: "The sold badge is readable in both themes. Availability is asymmetric per type — sold, ended, closed and depleted are different states — so the badges should distinguish them rather than collapsing everything into one word.",
517
+ expectedUiState: "The sold badge is legible in both themes. A sold product, an ended auction and a depleted code listing are distinguishable from their badges. A badge whose text vanishes in one theme is the failure.",
518
+ endResult: "Read-only; return the site to light mode afterwards.",
519
+ },
520
+ "checklist-admin-users-trust-homepage-section-all-types-creatable": {
521
+ roles: ["admin"],
522
+ startPage: "/admin",
523
+ steps: [
524
+ "Sign in as admin@letitrip.in / TempPass123!.",
525
+ "Open the homepage sections editor and open the section type picker.",
526
+ "Write down every type offered.",
527
+ "Compare the list against the section types the homepage can render.",
528
+ "Create one of each type not already present, saving after each.",
529
+ "Open / in a private window and check each new section renders.",
530
+ "Delete every section created.",
531
+ ],
532
+ expectedBehaviour: "Every renderable section type is creatable. A type the renderer supports but the picker omits is a feature nobody can reach, and a type the picker offers that the renderer does not handle produces a saved section that renders as nothing.",
533
+ expectedUiState: "The picker's types match what the homepage renders. Each created section appears publicly. A section that saves and renders nothing is the finding, named by type.",
534
+ endResult: "Every created section is deleted by the final step.",
535
+ },
536
+ "checklist-admin-users-trust-analytics-alert-threshold-is-numeric": {
537
+ roles: ["admin"],
538
+ startPage: "/admin/site",
539
+ steps: [
540
+ "Sign in as admin@letitrip.in / TempPass123!.",
541
+ "Open the analytics alert settings and find the threshold field.",
542
+ "Type abc into it and attempt to save.",
543
+ "Read where any error appears.",
544
+ "Type -5 and attempt to save, reading what happens.",
545
+ "Type 250 and save.",
546
+ "RELOAD and read the stored value.",
547
+ ],
548
+ inputs: { invalidText: "abc", negative: -5, valid: 250 },
549
+ expectedBehaviour: "The threshold accepts only a sensible number, validated on the field before any request. A text value stored where a number is expected produces a comparison that silently never fires — the alert simply never triggers, and nothing reports that it is broken.",
550
+ expectedUiState: "'abc' and -5 are both rejected on the field. 250 saves and survives the reload. A text value accepted here is the failure, and its consequence is an alert that never fires.",
551
+ expectedData: { threshold: 250 },
552
+ endResult: "Restore the original threshold value.",
553
+ },
554
+ "checklist-admin-users-trust-scammer-removed-badge-readable": {
555
+ roles: ["admin"],
556
+ startPage: "/admin/scammers",
557
+ steps: [
558
+ "Sign in as admin@letitrip.in / TempPass123!.",
559
+ "Open /admin/scammers and find a profile in the removed state, or set one to removed.",
560
+ "Read its status badge.",
561
+ "Read the badge against its background.",
562
+ "Switch to dark mode and read it again.",
563
+ "Check the removed status also appears as a filter chip and that the chip returns this row.",
564
+ ],
565
+ expectedBehaviour: "The removed status is a real stored value and is both rendered and filterable. The canonical field-name constants have been missing this exact value while the feature's own type file had it — so a badge that renders and a chip that does not, or the reverse, is the signature of two lists that have drifted.",
566
+ expectedUiState: "The removed badge is legible in both themes and a removed filter chip exists and returns this profile. A badge with no matching chip, or a chip returning nothing, is the drift.",
567
+ endResult: "Restore the profile's original status if it was changed.",
568
+ },
569
+ };
@@ -0,0 +1,2 @@
1
+ import type { AuthoredCase } from "./_types";
2
+ export declare const authored: Record<string, AuthoredCase>;