@mohasinac/appkit 3.8.1 → 3.9.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 (485) hide show
  1. package/dist/_internal/client/features/live/LiveItemDetailView.js +2 -2
  2. package/dist/_internal/client/features/lottery/LotteryAdminEditView.d.ts +4 -4
  3. package/dist/_internal/client/features/lottery/LotteryAdminEditView.js +8 -8
  4. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.d.ts +1 -1
  5. package/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +2 -2
  6. package/dist/_internal/server/features/bundles/actions.js +2 -2
  7. package/dist/_internal/server/features/bundles/og.d.ts +1 -1
  8. package/dist/_internal/server/features/bundles/og.js +4 -5
  9. package/dist/_internal/server/features/checkout/actions.js +57 -21
  10. package/dist/_internal/server/features/checkout/stock-restore.d.ts +19 -0
  11. package/dist/_internal/server/features/checkout/stock-restore.js +80 -0
  12. package/dist/_internal/server/features/checkout/upi-resolution.d.ts +11 -0
  13. package/dist/_internal/server/features/checkout/upi-resolution.js +28 -0
  14. package/dist/_internal/server/features/classified/og.js +1 -1
  15. package/dist/_internal/server/features/digital-code/og.js +1 -1
  16. package/dist/_internal/server/features/item-requests/og.d.ts +2 -2
  17. package/dist/_internal/server/features/item-requests/og.js +4 -5
  18. package/dist/_internal/server/features/live/og.js +1 -1
  19. package/dist/_internal/server/features/lottery/adapters.d.ts +2 -2
  20. package/dist/_internal/server/features/lottery/adapters.js +1 -1
  21. package/dist/_internal/server/features/orders/actions.d.ts +28 -0
  22. package/dist/_internal/server/features/orders/actions.js +239 -4
  23. package/dist/_internal/server/features/orders/adapters.js +3 -0
  24. package/dist/_internal/server/features/payments/data.js +3 -2
  25. package/dist/_internal/server/features/payouts/actions.d.ts +2 -2
  26. package/dist/_internal/server/features/payouts/actions.js +4 -3
  27. package/dist/_internal/server/features/pre-orders/service.d.ts +1 -1
  28. package/dist/_internal/server/features/pre-orders/service.js +3 -2
  29. package/dist/_internal/server/features/prize-draws/og.js +5 -5
  30. package/dist/_internal/server/features/products/og.js +1 -1
  31. package/dist/_internal/server/features/promotions/service.js +3 -1
  32. package/dist/_internal/server/features/refunds/actions.d.ts +2 -2
  33. package/dist/_internal/server/features/refunds/actions.js +7 -6
  34. package/dist/_internal/server/functions/firestore.js +1 -1
  35. package/dist/_internal/server/functions/scheduled.d.ts +4 -1
  36. package/dist/_internal/server/functions/scheduled.js +26 -2
  37. package/dist/_internal/server/jobs/core/emiInstallmentReminder.js +1 -1
  38. package/dist/_internal/server/jobs/core/hardBanCascade.d.ts +4 -0
  39. package/dist/_internal/server/jobs/core/hardBanCascade.js +15 -4
  40. package/dist/_internal/server/jobs/core/hardBanReinstatement.d.ts +16 -0
  41. package/dist/_internal/server/jobs/core/hardBanReinstatement.js +63 -0
  42. package/dist/_internal/server/jobs/core/jobRunners.js +3 -1
  43. package/dist/_internal/server/jobs/core/onScamReportCreate.js +1 -1
  44. package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.d.ts +10 -0
  45. package/dist/_internal/server/jobs/core/paymentReviewAutoApprove.js +60 -0
  46. package/dist/_internal/server/jobs/core/paymentWindowTimeout.d.ts +15 -0
  47. package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +59 -0
  48. package/dist/_internal/server/jobs/core/pendingOrderTimeout.d.ts +7 -0
  49. package/dist/_internal/server/jobs/core/pendingOrderTimeout.js +32 -6
  50. package/dist/_internal/server/jobs/handlers/hardBanReinstatement.d.ts +2 -0
  51. package/dist/_internal/server/jobs/handlers/hardBanReinstatement.js +2 -0
  52. package/dist/_internal/server/jobs/handlers/index.d.ts +3 -0
  53. package/dist/_internal/server/jobs/handlers/index.js +3 -0
  54. package/dist/_internal/server/jobs/handlers/messages.d.ts +4 -0
  55. package/dist/_internal/server/jobs/handlers/messages.js +4 -0
  56. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.d.ts +3 -3
  57. package/dist/_internal/server/jobs/handlers/onShipmentAllocationSync.js +12 -12
  58. package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.d.ts +1 -1
  59. package/dist/_internal/server/jobs/handlers/onShipmentItemWrite.js +5 -5
  60. package/dist/_internal/server/jobs/handlers/paymentReviewAutoApprove.d.ts +2 -0
  61. package/dist/_internal/server/jobs/handlers/paymentReviewAutoApprove.js +2 -0
  62. package/dist/_internal/server/jobs/handlers/paymentWindowTimeout.d.ts +2 -0
  63. package/dist/_internal/server/jobs/handlers/paymentWindowTimeout.js +2 -0
  64. package/dist/_internal/shared/actions/action-registry.js +27 -0
  65. package/dist/_internal/shared/checkout/order-math.js +3 -2
  66. package/dist/_internal/shared/checkout/rules/_defaults.js +1 -0
  67. package/dist/_internal/shared/checkout/rules/preorder.rule.js +7 -0
  68. package/dist/_internal/shared/checkout/rules/prize-draw.rule.js +7 -0
  69. package/dist/_internal/shared/checkout/rules/types.d.ts +11 -0
  70. package/dist/_internal/shared/features/auctions/errors.js +1 -1
  71. package/dist/_internal/shared/features/categories/bundle-copy.d.ts +0 -1
  72. package/dist/_internal/shared/features/categories/bundle-copy.js +0 -1
  73. package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +6 -6
  74. package/dist/_internal/shared/features/categories/bundle-schemas.js +2 -2
  75. package/dist/_internal/shared/features/checkout/config.d.ts +3 -3
  76. package/dist/_internal/shared/features/checkout/config.js +3 -3
  77. package/dist/_internal/shared/features/emi/schedule.d.ts +6 -6
  78. package/dist/_internal/shared/features/emi/schedule.js +10 -9
  79. package/dist/_internal/shared/features/promotions/errors.js +1 -1
  80. package/dist/_internal/shared/fees/calculator.d.ts +5 -5
  81. package/dist/_internal/shared/fees/calculator.js +19 -19
  82. package/dist/client.d.ts +1 -1
  83. package/dist/client.js +1 -1
  84. package/dist/constants/api-endpoints.d.ts +9 -0
  85. package/dist/constants/api-endpoints.js +3 -0
  86. package/dist/constants/field-names.d.ts +4 -0
  87. package/dist/constants/field-names.js +4 -0
  88. package/dist/features/admin/components/AdminArtView.js +2 -2
  89. package/dist/features/admin/components/AdminBidsView.js +2 -2
  90. package/dist/features/admin/components/AdminBundleEditorView.d.ts +1 -1
  91. package/dist/features/admin/components/AdminBundleEditorView.js +8 -8
  92. package/dist/features/admin/components/AdminBundlesView.js +6 -6
  93. package/dist/features/admin/components/AdminClassifiedView.js +2 -2
  94. package/dist/features/admin/components/AdminDigitalCodesView.js +2 -2
  95. package/dist/features/admin/components/AdminLiveView.js +2 -2
  96. package/dist/features/admin/components/AdminOrderEditorView.d.ts +6 -1
  97. package/dist/features/admin/components/AdminOrderEditorView.js +45 -5
  98. package/dist/features/admin/components/AdminOrdersView.js +8 -3
  99. package/dist/features/admin/components/AdminPayoutsView.js +2 -2
  100. package/dist/features/admin/components/AdminPrizeDrawsView.js +2 -2
  101. package/dist/features/admin/components/AdminReturnRequestsView.js +2 -2
  102. package/dist/features/admin/components/AdminSiteSettingsView.js +11 -11
  103. package/dist/features/admin/components/AdminStickersView.js +2 -2
  104. package/dist/features/admin/components/AdminSupportTicketDetailView.js +1 -1
  105. package/dist/features/admin/hooks/useAdminListingData.d.ts +1 -1
  106. package/dist/features/admin/hooks/useAdminListingData.js +3 -2
  107. package/dist/features/admin/schemas/firestore.d.ts +9 -7
  108. package/dist/features/admin/schemas/firestore.js +4 -3
  109. package/dist/features/auctions/components/AuctionBidsTable.js +3 -3
  110. package/dist/features/auth/checkout-value-otp.d.ts +46 -0
  111. package/dist/features/auth/checkout-value-otp.js +73 -0
  112. package/dist/features/auth/repository/user.repository.d.ts +6 -0
  113. package/dist/features/auth/repository/user.repository.js +19 -0
  114. package/dist/features/auth/schemas/firestore.d.ts +10 -0
  115. package/dist/features/auth/schemas/firestore.js +2 -0
  116. package/dist/features/cart/actions/cart-actions.d.ts +1 -1
  117. package/dist/features/cart/actions/cart-actions.js +4 -4
  118. package/dist/features/cart/components/CartView.d.ts +2 -2
  119. package/dist/features/cart/components/ShippingPicker.d.ts +4 -4
  120. package/dist/features/cart/components/ShippingPicker.js +11 -11
  121. package/dist/features/cart/repository/cart.repository.d.ts +1 -1
  122. package/dist/features/cart/repository/cart.repository.js +2 -2
  123. package/dist/features/cart/schemas/firestore.d.ts +2 -2
  124. package/dist/features/catalogue/components/CatalogueItemEditorView.js +3 -3
  125. package/dist/features/catalogue/components/PublicCatalogueView.js +2 -2
  126. package/dist/features/catalogue/schemas/validation.js +1 -1
  127. package/dist/features/categories/components/BundleCollage.js +2 -2
  128. package/dist/features/categories/components/BundleDetailView.js +2 -2
  129. package/dist/features/categories/components/BundleItemsPicker.d.ts +1 -1
  130. package/dist/features/categories/components/BundleItemsPicker.js +2 -2
  131. package/dist/features/categories/components/CategoryBundlesListing.js +2 -2
  132. package/dist/features/categories/schemas/firestore.d.ts +1 -1
  133. package/dist/features/categories/schemas/index.d.ts +3 -3
  134. package/dist/features/categories/schemas/index.js +2 -2
  135. package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +16 -0
  136. package/dist/features/checkout/actions/checkout-value-otp-actions.js +83 -0
  137. package/dist/features/checkout/actions/index.d.ts +1 -0
  138. package/dist/features/checkout/actions/index.js +1 -0
  139. package/dist/features/checkout/schemas/firestore.d.ts +1 -1
  140. package/dist/features/classified/components/index.d.ts +0 -4
  141. package/dist/features/classified/components/index.js +0 -2
  142. package/dist/features/digital-codes/components/index.d.ts +0 -4
  143. package/dist/features/digital-codes/components/index.js +0 -2
  144. package/dist/features/events/schemas/index.d.ts +1 -1
  145. package/dist/features/events/schemas/index.js +1 -1
  146. package/dist/features/homepage/components/FeaturedBundlesSection.js +2 -2
  147. package/dist/features/live/components/index.d.ts +0 -4
  148. package/dist/features/live/components/index.js +0 -2
  149. package/dist/features/lottery/types/index.d.ts +3 -3
  150. package/dist/features/lottery/types/index.js +5 -5
  151. package/dist/features/orders/components/OrderPaymentSummary.js +2 -2
  152. package/dist/features/orders/components/OrderSiblingPayments.js +1 -1
  153. package/dist/features/orders/components/RefundHistoryTable.js +1 -1
  154. package/dist/features/orders/components/RefundRequestView.js +1 -1
  155. package/dist/features/orders/constants/payment-window.d.ts +10 -0
  156. package/dist/features/orders/constants/payment-window.js +10 -0
  157. package/dist/features/orders/repository/orders.repository.d.ts +25 -0
  158. package/dist/features/orders/repository/orders.repository.js +50 -1
  159. package/dist/features/orders/schemas/firestore.d.ts +50 -2
  160. package/dist/features/orders/schemas/index.d.ts +24 -24
  161. package/dist/features/orders/schemas/index.js +20 -20
  162. package/dist/features/orders/types/index.d.ts +4 -0
  163. package/dist/features/orders/utils/bundle-grouping.d.ts +1 -1
  164. package/dist/features/orders/utils/bundle-grouping.js +1 -1
  165. package/dist/features/payments/schemas/index.d.ts +10 -10
  166. package/dist/features/payments/schemas/index.js +9 -9
  167. package/dist/features/pre-orders/components/PreOrderDetailPageView.js +2 -2
  168. package/dist/features/products/components/ArtStickersListView.d.ts +7 -0
  169. package/dist/features/products/components/ArtStickersListView.js +57 -0
  170. package/dist/features/products/components/GroupSettingsPanel.js +1 -1
  171. package/dist/features/products/components/MakeOfferButton.js +3 -3
  172. package/dist/features/products/components/MarketplaceBundleCard.d.ts +1 -1
  173. package/dist/features/products/components/MarketplaceBundleCard.js +2 -2
  174. package/dist/features/products/components/PrizeDrawCollage.js +2 -2
  175. package/dist/features/products/components/PrizeDrawItemsEditor.js +2 -2
  176. package/dist/features/products/components/PrizeRevealModal.js +1 -1
  177. package/dist/features/products/components/ProductDetailPageView.js +2 -9
  178. package/dist/features/products/components/ProductForm.js +2 -2
  179. package/dist/features/products/components/ProductGrid.js +2 -2
  180. package/dist/features/products/components/ProductsIndexListing.d.ts +13 -1
  181. package/dist/features/products/components/ProductsIndexListing.js +7 -5
  182. package/dist/features/products/components/ProductsIndexPageView.js +6 -1
  183. package/dist/features/products/constants/listing-tabs.d.ts +42 -17
  184. package/dist/features/products/constants/listing-tabs.js +25 -6
  185. package/dist/features/products/schemas/catalog-product.d.ts +5 -5
  186. package/dist/features/products/schemas/catalog-product.js +1 -1
  187. package/dist/features/products/schemas/firestore.d.ts +5 -5
  188. package/dist/features/products/schemas/firestore.js +2 -2
  189. package/dist/features/products/types/index.d.ts +5 -2
  190. package/dist/features/promotions/components/CouponCard.js +2 -2
  191. package/dist/features/promotions/schemas/firestore.d.ts +2 -0
  192. package/dist/features/promotions/schemas/firestore.js +1 -0
  193. package/dist/features/promotions/schemas/index.d.ts +14 -14
  194. package/dist/features/promotions/schemas/index.js +6 -6
  195. package/dist/features/scams/components/ScamProfileView.js +3 -7
  196. package/dist/features/scams/components/ScamRegistryView.js +2 -6
  197. package/dist/features/scams/schemas/firestore.d.ts +1 -1
  198. package/dist/features/search/components/Search.d.ts +1 -1
  199. package/dist/features/seller/actions/offer-actions.js +1 -1
  200. package/dist/features/seller/components/PrintCenterView.js +2 -2
  201. package/dist/features/seller/components/QuickProductForm.js +5 -5
  202. package/dist/features/seller/components/SellerArtView.js +2 -2
  203. package/dist/features/seller/components/SellerAuctionsView.js +2 -2
  204. package/dist/features/seller/components/SellerBidsView.js +2 -2
  205. package/dist/features/seller/components/SellerBundlesView.js +6 -6
  206. package/dist/features/seller/components/SellerClassifiedView.js +2 -2
  207. package/dist/features/seller/components/SellerDigitalCodesView.js +2 -2
  208. package/dist/features/seller/components/SellerLiveView.js +2 -2
  209. package/dist/features/seller/components/SellerOffersView.js +2 -2
  210. package/dist/features/seller/components/SellerOrdersView.js +3 -3
  211. package/dist/features/seller/components/SellerPayoutRequestView.js +2 -2
  212. package/dist/features/seller/components/SellerPayoutSettingsView.js +2 -2
  213. package/dist/features/seller/components/SellerPayoutsView.js +2 -2
  214. package/dist/features/seller/components/SellerPreOrdersView.js +2 -2
  215. package/dist/features/seller/components/SellerPrizeDrawsView.js +2 -2
  216. package/dist/features/seller/components/SellerProductShell.js +8 -8
  217. package/dist/features/seller/components/SellerProductsView.js +1 -1
  218. package/dist/features/seller/components/SellerShippingView.js +6 -6
  219. package/dist/features/seller/components/SellerStickersView.js +2 -2
  220. package/dist/features/seller/hooks/useSellerListingData.d.ts +1 -1
  221. package/dist/features/seller/hooks/useSellerListingData.js +3 -2
  222. package/dist/features/shipments/components/AdminShipmentEditorView.js +10 -10
  223. package/dist/features/shipments/components/AdminShipmentLotItemsView.js +4 -4
  224. package/dist/features/shipments/components/AdminShipmentProjectionsView.js +5 -5
  225. package/dist/features/shipments/components/AdminShipmentsView.js +4 -4
  226. package/dist/features/shipments/repository/shipment-lots.repository.d.ts +2 -2
  227. package/dist/features/shipments/repository/shipment-lots.repository.js +8 -8
  228. package/dist/features/shipments/schemas/firestore.d.ts +21 -21
  229. package/dist/features/shipments/schemas/firestore.js +9 -9
  230. package/dist/features/shipments/schemas/validation.d.ts +30 -30
  231. package/dist/features/shipments/schemas/validation.js +6 -6
  232. package/dist/features/shipments/utils/cost-allocation.d.ts +5 -5
  233. package/dist/features/shipments/utils/cost-allocation.js +39 -38
  234. package/dist/features/store-extensions/schemas/firestore.d.ts +5 -5
  235. package/dist/features/stores/components/StoreDetailLayoutView.js +9 -13
  236. package/dist/features/stores/schemas/firestore.d.ts +7 -7
  237. package/dist/features/stores/schemas/index.d.ts +84 -84
  238. package/dist/features/stores/schemas/index.js +5 -5
  239. package/dist/features/tester/seed-data/categories-tester-seed-data.js +1 -1
  240. package/dist/features/tester/seed-data/products-tester-seed-data.js +6 -6
  241. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +9 -2
  242. package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +8 -1
  243. package/dist/features/whatsapp-bot/helpers/whatsapp.js +13 -2
  244. package/dist/features/whatsapp-bot/types/index.d.ts +9 -1
  245. package/dist/index.d.ts +4 -7
  246. package/dist/index.js +9 -5
  247. package/dist/next/routing/route-map.d.ts +2 -0
  248. package/dist/next/routing/route-map.js +6 -0
  249. package/dist/schemas/firestore-helpers.d.ts +2 -2
  250. package/dist/schemas/firestore-helpers.js +2 -2
  251. package/dist/schemas/registry.d.ts +73 -73
  252. package/dist/security/index.d.ts +2 -1
  253. package/dist/security/index.js +5 -1
  254. package/dist/security/pii-encrypt.d.ts +2 -53
  255. package/dist/security/pii-encrypt.js +19 -100
  256. package/dist/security/pii-mask.d.ts +67 -0
  257. package/dist/security/pii-mask.js +100 -0
  258. package/dist/seed/bids-seed-data.js +6 -6
  259. package/dist/seed/blog-posts-seed-data.js +1 -0
  260. package/dist/seed/cart-seed-data.js +13 -13
  261. package/dist/seed/catalogue-seed-data.js +6 -6
  262. package/dist/seed/categories-seed-data.js +5 -5
  263. package/dist/seed/claimed-coupons-seed-data.js +3 -3
  264. package/dist/seed/coupons-seed-data.js +20 -20
  265. package/dist/seed/events-seed-data.js +27 -27
  266. package/dist/seed/factories/bid.factory.js +1 -1
  267. package/dist/seed/faq-seed-data.js +20 -1
  268. package/dist/seed/grouped-listings-seed-data.d.ts +2 -2
  269. package/dist/seed/grouped-listings-seed-data.js +3 -3
  270. package/dist/seed/offers-seed-data.js +19 -19
  271. package/dist/seed/orders-seed-data.js +29 -29
  272. package/dist/seed/payouts-seed-data.js +7 -7
  273. package/dist/seed/products-auctions-seed-data.js +6 -6
  274. package/dist/seed/products-preorders-seed-data.d.ts +2 -2
  275. package/dist/seed/products-preorders-seed-data.js +1 -1
  276. package/dist/seed/products-standard-seed-data.js +8 -8
  277. package/dist/seed/scammers-seed-data.js +2 -2
  278. package/dist/seed/shipments-seed-data.js +29 -29
  279. package/dist/seed/site-settings-seed-data.js +3 -2
  280. package/dist/seed/store-extensions-seed-data.js +8 -8
  281. package/dist/seed/stores-seed-data.js +37 -8
  282. package/dist/seed/users-seed-data.js +38 -1
  283. package/dist/server-entry.d.ts +1 -3
  284. package/dist/server-entry.js +1 -3
  285. package/dist/server.d.ts +2 -1
  286. package/dist/server.js +3 -1
  287. package/dist/ui/components/PriceDisplay.js +3 -12
  288. package/dist/utils/number.formatter.d.ts +2 -7
  289. package/dist/utils/number.formatter.js +3 -8
  290. package/package.json +1 -1
  291. package/scripts/seed-cli.mjs +17 -3
  292. package/dist/_internal/client/scaffolds/DashboardScaffold.d.ts +0 -34
  293. package/dist/_internal/client/scaffolds/DashboardScaffold.js +0 -26
  294. package/dist/_internal/client/theme/__tests__/ThemeProvider.test.d.ts +0 -1
  295. package/dist/_internal/client/theme/__tests__/ThemeProvider.test.js +0 -109
  296. package/dist/_internal/server/features/auctions/__tests__/service.test.d.ts +0 -1
  297. package/dist/_internal/server/features/auctions/__tests__/service.test.js +0 -140
  298. package/dist/_internal/server/features/checkout/__tests__/actions.test.d.ts +0 -1
  299. package/dist/_internal/server/features/checkout/__tests__/actions.test.js +0 -600
  300. package/dist/_internal/server/features/refunds/__tests__/actions.test.d.ts +0 -1
  301. package/dist/_internal/server/features/refunds/__tests__/actions.test.js +0 -263
  302. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.d.ts +0 -1
  303. package/dist/_internal/server/jobs/core/__tests__/auctionSettlement.test.js +0 -249
  304. package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.d.ts +0 -1
  305. package/dist/_internal/server/jobs/core/__tests__/couponExpiry.test.js +0 -65
  306. package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.d.ts +0 -1
  307. package/dist/_internal/server/jobs/core/__tests__/listingProcessor.test.js +0 -163
  308. package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.d.ts +0 -1
  309. package/dist/_internal/server/jobs/core/__tests__/mediaTmpCleanup.test.js +0 -115
  310. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.d.ts +0 -1
  311. package/dist/_internal/server/jobs/core/__tests__/onBidPlaced.test.js +0 -201
  312. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.d.ts +0 -1
  313. package/dist/_internal/server/jobs/core/__tests__/onOrderCreate.test.js +0 -169
  314. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.d.ts +0 -1
  315. package/dist/_internal/server/jobs/core/__tests__/onOrderStatusChange.test.js +0 -148
  316. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.d.ts +0 -1
  317. package/dist/_internal/server/jobs/core/__tests__/onProductStockChange.test.js +0 -210
  318. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.d.ts +0 -1
  319. package/dist/_internal/server/jobs/core/__tests__/onReviewWrite.test.js +0 -190
  320. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.d.ts +0 -1
  321. package/dist/_internal/server/jobs/core/__tests__/onUserBanChange.test.js +0 -161
  322. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.d.ts +0 -1
  323. package/dist/_internal/server/jobs/core/__tests__/payoutBatch.test.js +0 -302
  324. package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.d.ts +0 -1
  325. package/dist/_internal/server/jobs/core/__tests__/pendingOrderTimeout.test.js +0 -96
  326. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.d.ts +0 -1
  327. package/dist/_internal/server/jobs/core/__tests__/triggerEventRaffle.test.js +0 -252
  328. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.d.ts +0 -1
  329. package/dist/_internal/server/jobs/core/__tests__/wrapJobHandler.test.js +0 -129
  330. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.d.ts +0 -15
  331. package/dist/_internal/server/jobs/core/onCatalogueSubmittedForApproval.js +0 -38
  332. package/dist/_internal/server/providers/index.d.ts +0 -11
  333. package/dist/_internal/server/providers/index.js +0 -11
  334. package/dist/_internal/server/providers/payment/razorpay-mock.d.ts +0 -52
  335. package/dist/_internal/server/providers/payment/razorpay-mock.js +0 -118
  336. package/dist/_internal/server/providers/resolve.d.ts +0 -36
  337. package/dist/_internal/server/providers/resolve.js +0 -31
  338. package/dist/_internal/server/providers/shipping/shiprocket-mock.d.ts +0 -29
  339. package/dist/_internal/server/providers/shipping/shiprocket-mock.js +0 -152
  340. package/dist/_internal/shared/types/__tests__/action-result.test.d.ts +0 -1
  341. package/dist/_internal/shared/types/__tests__/action-result.test.js +0 -65
  342. package/dist/errors/__tests__/error-mapping.test.d.ts +0 -1
  343. package/dist/errors/__tests__/error-mapping.test.js +0 -122
  344. package/dist/errors/__tests__/safe-read.test.d.ts +0 -1
  345. package/dist/errors/__tests__/safe-read.test.js +0 -39
  346. package/dist/features/addresses/repository/__tests__/addresses.repository.test.d.ts +0 -1
  347. package/dist/features/addresses/repository/__tests__/addresses.repository.test.js +0 -386
  348. package/dist/features/admin/components/AdminListingScaffold.d.ts +0 -41
  349. package/dist/features/admin/components/AdminListingScaffold.js +0 -68
  350. package/dist/features/admin/components/QuickActionsPanel.d.ts +0 -15
  351. package/dist/features/admin/components/QuickActionsPanel.js +0 -5
  352. package/dist/features/admin/repository/__tests__/notification.repository.test.d.ts +0 -1
  353. package/dist/features/admin/repository/__tests__/notification.repository.test.js +0 -356
  354. package/dist/features/admin/repository/__tests__/site-settings.repository.test.d.ts +0 -1
  355. package/dist/features/admin/repository/__tests__/site-settings.repository.test.js +0 -298
  356. package/dist/features/auctions/repository/__tests__/bid.repository.test.d.ts +0 -1
  357. package/dist/features/auctions/repository/__tests__/bid.repository.test.js +0 -290
  358. package/dist/features/auctions/repository/auctions.repository.d.ts +0 -12
  359. package/dist/features/auctions/repository/auctions.repository.js +0 -42
  360. package/dist/features/auth/repository/__tests__/session.repository.test.d.ts +0 -1
  361. package/dist/features/auth/repository/__tests__/session.repository.test.js +0 -310
  362. package/dist/features/auth/repository/__tests__/session.test.d.ts +0 -1
  363. package/dist/features/auth/repository/__tests__/session.test.js +0 -146
  364. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.d.ts +0 -1
  365. package/dist/features/auth/repository/__tests__/sms-counter.repository.test.js +0 -171
  366. package/dist/features/auth/repository/__tests__/sms-counter.test.d.ts +0 -1
  367. package/dist/features/auth/repository/__tests__/sms-counter.test.js +0 -88
  368. package/dist/features/auth/repository/__tests__/token.repository.test.d.ts +0 -1
  369. package/dist/features/auth/repository/__tests__/token.repository.test.js +0 -260
  370. package/dist/features/auth/repository/__tests__/token.test.d.ts +0 -1
  371. package/dist/features/auth/repository/__tests__/token.test.js +0 -140
  372. package/dist/features/auth/repository/__tests__/user.repository.test.d.ts +0 -1
  373. package/dist/features/auth/repository/__tests__/user.repository.test.js +0 -352
  374. package/dist/features/auth/repository/__tests__/user.test.d.ts +0 -1
  375. package/dist/features/auth/repository/__tests__/user.test.js +0 -226
  376. package/dist/features/before-after/repository/before-after.repository.d.ts +0 -13
  377. package/dist/features/before-after/repository/before-after.repository.js +0 -36
  378. package/dist/features/before-after/server.d.ts +0 -6
  379. package/dist/features/before-after/server.js +0 -6
  380. package/dist/features/cart/repository/__tests__/cart.repository.test.d.ts +0 -1
  381. package/dist/features/cart/repository/__tests__/cart.repository.test.js +0 -371
  382. package/dist/features/categories/repository/__tests__/categories.repository.test.d.ts +0 -1
  383. package/dist/features/categories/repository/__tests__/categories.repository.test.js +0 -813
  384. package/dist/features/collections/repository/collections.repository.d.ts +0 -8
  385. package/dist/features/collections/repository/collections.repository.js +0 -16
  386. package/dist/features/collections/server.d.ts +0 -6
  387. package/dist/features/collections/server.js +0 -6
  388. package/dist/features/events/repository/__tests__/event.repository.test.d.ts +0 -1
  389. package/dist/features/events/repository/__tests__/event.repository.test.js +0 -299
  390. package/dist/features/faq/repository/__tests__/faqs.repository.test.d.ts +0 -1
  391. package/dist/features/faq/repository/__tests__/faqs.repository.test.js +0 -311
  392. package/dist/features/forms/Form.d.ts +0 -25
  393. package/dist/features/forms/Form.js +0 -37
  394. package/dist/features/history/repository/__tests__/user-history.repository.test.d.ts +0 -1
  395. package/dist/features/history/repository/__tests__/user-history.repository.test.js +0 -180
  396. package/dist/features/homepage/repository/__tests__/carousel.repository.test.d.ts +0 -1
  397. package/dist/features/homepage/repository/__tests__/carousel.repository.test.js +0 -182
  398. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.d.ts +0 -1
  399. package/dist/features/homepage/repository/__tests__/homepage-sections.repository.test.js +0 -185
  400. package/dist/features/layout/ListingLayout.d.ts +0 -34
  401. package/dist/features/layout/ListingLayout.js +0 -103
  402. package/dist/features/messages/repository/__tests__/conversations.repository.test.d.ts +0 -1
  403. package/dist/features/messages/repository/__tests__/conversations.repository.test.js +0 -257
  404. package/dist/features/orders/repository/__tests__/orders.repository.test.d.ts +0 -1
  405. package/dist/features/orders/repository/__tests__/orders.repository.test.js +0 -211
  406. package/dist/features/payments/repository/__tests__/payout.repository.test.d.ts +0 -1
  407. package/dist/features/payments/repository/__tests__/payout.repository.test.js +0 -292
  408. package/dist/features/pre-orders/repository/preorders.repository.d.ts +0 -8
  409. package/dist/features/pre-orders/repository/preorders.repository.js +0 -25
  410. package/dist/features/products/repository/__tests__/product-features.repository.test.d.ts +0 -1
  411. package/dist/features/products/repository/__tests__/product-features.repository.test.js +0 -329
  412. package/dist/features/products/repository/__tests__/products.repository.test.d.ts +0 -1
  413. package/dist/features/products/repository/__tests__/products.repository.test.js +0 -607
  414. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.d.ts +0 -1
  415. package/dist/features/promotions/repository/__tests__/claimed-coupons.repository.test.js +0 -219
  416. package/dist/features/promotions/repository/__tests__/coupons.repository.test.d.ts +0 -1
  417. package/dist/features/promotions/repository/__tests__/coupons.repository.test.js +0 -480
  418. package/dist/features/promotions/repository/promotions.repository.d.ts +0 -14
  419. package/dist/features/promotions/repository/promotions.repository.js +0 -43
  420. package/dist/features/reviews/repository/__tests__/reviews.repository.test.d.ts +0 -1
  421. package/dist/features/reviews/repository/__tests__/reviews.repository.test.js +0 -327
  422. package/dist/features/scams/repository/__tests__/scammer.repository.test.d.ts +0 -1
  423. package/dist/features/scams/repository/__tests__/scammer.repository.test.js +0 -385
  424. package/dist/features/search/repository/__tests__/search.repository.test.d.ts +0 -1
  425. package/dist/features/search/repository/__tests__/search.repository.test.js +0 -369
  426. package/dist/features/seller/components/SellerStatCard.d.ts +0 -14
  427. package/dist/features/seller/components/SellerStatCard.js +0 -6
  428. package/dist/features/seller/components/seller-products-styles.d.ts +0 -7
  429. package/dist/features/seller/components/seller-products-styles.js +0 -14
  430. package/dist/features/seller/repository/__tests__/offer.repository.test.d.ts +0 -1
  431. package/dist/features/seller/repository/__tests__/offer.repository.test.js +0 -458
  432. package/dist/features/seller/repository/seller.repository.d.ts +0 -22
  433. package/dist/features/seller/repository/seller.repository.js +0 -72
  434. package/dist/features/site-settings/components/__tests__/ThemeManagerView.test.d.ts +0 -1
  435. package/dist/features/site-settings/components/__tests__/ThemeManagerView.test.js +0 -37
  436. package/dist/features/stores/repository/__tests__/store.repository.test.d.ts +0 -1
  437. package/dist/features/stores/repository/__tests__/store.repository.test.js +0 -261
  438. package/dist/features/stores/repository/stores.repository.d.ts +0 -11
  439. package/dist/features/stores/repository/stores.repository.js +0 -37
  440. package/dist/features/support/repository/__tests__/support.repository.test.d.ts +0 -1
  441. package/dist/features/support/repository/__tests__/support.repository.test.js +0 -312
  442. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.d.ts +0 -1
  443. package/dist/features/wishlist/repository/__tests__/user-wishlist.repository.test.js +0 -139
  444. package/dist/features/wishlist/repository/wishlist.repository.d.ts +0 -13
  445. package/dist/features/wishlist/repository/wishlist.repository.js +0 -31
  446. package/dist/providers/db-firebase/__tests__/filter-aliases.test.d.ts +0 -1
  447. package/dist/providers/db-firebase/__tests__/filter-aliases.test.js +0 -93
  448. package/dist/providers/shipping-shiprocket/index.d.ts +0 -297
  449. package/dist/providers/shipping-shiprocket/index.js +0 -194
  450. package/dist/providers/shipping-shiprocket/shiprocket-provider.d.ts +0 -45
  451. package/dist/providers/shipping-shiprocket/shiprocket-provider.js +0 -168
  452. package/dist/react/contexts/ThemeContext.d.ts +0 -13
  453. package/dist/react/contexts/ThemeContext.js +0 -64
  454. package/dist/schemas/webhooks/shiprocket.d.ts +0 -30
  455. package/dist/schemas/webhooks/shiprocket.js +0 -22
  456. package/dist/seed/actions/demo-seed-actions.d.ts +0 -42
  457. package/dist/seed/actions/demo-seed-actions.js +0 -36
  458. package/dist/seed/actions/index.d.ts +0 -1
  459. package/dist/seed/actions/index.js +0 -1
  460. package/dist/seed/sub-listings-seed-data.d.ts +0 -123
  461. package/dist/seed/sub-listings-seed-data.js +0 -447
  462. package/dist/seed/tester-checklist-seed-data.d.ts +0 -2
  463. package/dist/seed/tester-checklist-seed-data.js +0 -248
  464. package/dist/ui/components/DashboardStatsCard.d.ts +0 -15
  465. package/dist/ui/components/DashboardStatsCard.js +0 -27
  466. package/dist/ui/components/DashboardStatsCard.style.css +0 -68
  467. package/dist/ui/components/DynamicSelect.d.ts +0 -23
  468. package/dist/ui/components/DynamicSelect.js +0 -77
  469. package/dist/ui/components/DynamicSelect.style.css +0 -101
  470. package/dist/ui/components/InlineCreateSelect.d.ts +0 -48
  471. package/dist/ui/components/InlineCreateSelect.js +0 -75
  472. package/dist/ui/components/ListingViewShell.d.ts +0 -37
  473. package/dist/ui/components/ListingViewShell.js +0 -9
  474. package/dist/ui/components/PaginatedMultiSelect.d.ts +0 -28
  475. package/dist/ui/components/PaginatedMultiSelect.js +0 -141
  476. package/dist/ui/components/PaginatedMultiSelect.style.css +0 -272
  477. package/dist/ui/components/SectionTabs.d.ts +0 -19
  478. package/dist/ui/components/SectionTabs.js +0 -66
  479. package/dist/ui/components/SectionTabs.style.css +0 -164
  480. package/dist/ui/components/__tests__/BulkActionBar.test.d.ts +0 -1
  481. package/dist/ui/components/__tests__/BulkActionBar.test.js +0 -96
  482. package/dist/ui/components/__tests__/ListingToolbar.test.d.ts +0 -1
  483. package/dist/ui/components/__tests__/ListingToolbar.test.js +0 -125
  484. package/dist/ui/components/__tests__/new-primitives.test.d.ts +0 -1
  485. package/dist/ui/components/__tests__/new-primitives.test.js +0 -187
@@ -1,813 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import { makeMockDb, makeSnap, makeQuerySnap } from "../../../../../tests/helpers/mock-firestore";
3
- const { db, mockDocRef, mockCollection, mockQuery, mockBatch } = makeMockDb();
4
- vi.mock("../../../../providers/db-firebase/admin", () => ({
5
- getAdminDb: () => db,
6
- }));
7
- vi.mock("../../../../providers/db-firebase", async (importOriginal) => {
8
- const actual = await importOriginal();
9
- return { ...actual, prepareForFirestore: (d) => d };
10
- });
11
- vi.mock("../../../../contracts/field-ops", () => ({
12
- serverTimestamp: () => new Date(),
13
- increment: (n) => n,
14
- arrayUnion: (...args) => args,
15
- arrayRemove: (...args) => args,
16
- deleteField: () => null,
17
- registerFieldOps: vi.fn(),
18
- }));
19
- vi.mock("../../../../errors/normalize", () => ({ normalizeError: vi.fn() }));
20
- vi.mock("../../../../monitoring", () => ({
21
- serverLogger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn() },
22
- }));
23
- import { CategoriesRepository } from "../categories.repository";
24
- import { MIN_ITEMS_FOR_FEATURED } from "../../schemas";
25
- const repo = new CategoriesRepository();
26
- function makeCategoryDoc(overrides = {}) {
27
- return {
28
- id: "category-action-figures",
29
- name: "Action Figures",
30
- slug: "action-figures",
31
- categoryType: "category",
32
- tier: 0,
33
- parentIds: [],
34
- rootId: "category-action-figures",
35
- path: "action-figures",
36
- ancestors: [],
37
- childrenIds: [],
38
- isLeaf: true,
39
- isActive: true,
40
- isBrand: false,
41
- isFeatured: false,
42
- isSearchable: true,
43
- order: 1,
44
- metrics: {
45
- productCount: 0,
46
- productIds: [],
47
- auctionCount: 0,
48
- auctionIds: [],
49
- totalProductCount: 0,
50
- totalAuctionCount: 0,
51
- totalItemCount: 0,
52
- lastUpdated: new Date(),
53
- },
54
- display: {},
55
- seo: {},
56
- createdAt: new Date(),
57
- updatedAt: new Date(),
58
- ...overrides,
59
- };
60
- }
61
- beforeEach(() => {
62
- // resetAllMocks clears call history AND the mockResolvedValueOnce queue,
63
- // preventing unconsumed "once" values from bleeding into the next test.
64
- vi.resetAllMocks();
65
- db.collection.mockReturnValue(mockCollection);
66
- db.batch.mockReturnValue(mockBatch);
67
- mockCollection.doc.mockReturnValue(mockDocRef);
68
- mockCollection.where.mockReturnValue(mockQuery);
69
- mockCollection.orderBy = vi.fn().mockReturnValue(mockQuery);
70
- mockCollection.get = vi.fn().mockResolvedValue(makeQuerySnap([]));
71
- mockQuery.where.mockReturnValue(mockQuery);
72
- mockQuery.orderBy.mockReturnValue(mockQuery);
73
- mockQuery.limit.mockReturnValue(mockQuery);
74
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
75
- mockDocRef.get.mockResolvedValue(makeSnap(null));
76
- mockDocRef.set.mockResolvedValue(undefined);
77
- mockDocRef.update.mockResolvedValue(undefined);
78
- mockDocRef.delete.mockResolvedValue(undefined);
79
- mockBatch.update.mockReturnValue(undefined);
80
- mockBatch.delete.mockReturnValue(undefined);
81
- mockBatch.commit.mockResolvedValue(undefined);
82
- });
83
- // ---------------------------------------------------------------------------
84
- // createWithHierarchy — root category (no parent)
85
- // ---------------------------------------------------------------------------
86
- describe("CategoriesRepository.createWithHierarchy — root category", () => {
87
- it("creates a root category with tier 0 when no parentId provided", async () => {
88
- // No parent lookup (parentIds is empty) — first get is findByIdOrFail at the end
89
- const createdDoc = makeCategoryDoc({ tier: 0, parentIds: [] });
90
- mockDocRef.get.mockResolvedValue(makeSnap(createdDoc, createdDoc.id));
91
- const result = await repo.createWithHierarchy({
92
- name: "Action Figures",
93
- slug: "action-figures",
94
- categoryType: "category",
95
- isActive: true,
96
- isBrand: false,
97
- isSearchable: true,
98
- order: 1,
99
- display: {},
100
- seo: {},
101
- });
102
- expect(result.tier).toBe(0);
103
- });
104
- it("sets parentIds: [] for a root category", async () => {
105
- const createdDoc = makeCategoryDoc({ tier: 0, parentIds: [] });
106
- mockDocRef.get.mockResolvedValue(makeSnap(createdDoc, createdDoc.id));
107
- const result = await repo.createWithHierarchy({
108
- name: "Action Figures",
109
- slug: "action-figures",
110
- categoryType: "category",
111
- isActive: true,
112
- isBrand: false,
113
- isSearchable: true,
114
- order: 1,
115
- display: {},
116
- seo: {},
117
- });
118
- expect(result.parentIds).toEqual([]);
119
- });
120
- it("sets isLeaf: true on a freshly created root category", async () => {
121
- const createdDoc = makeCategoryDoc({ isLeaf: true });
122
- mockDocRef.get.mockResolvedValue(makeSnap(createdDoc, createdDoc.id));
123
- const result = await repo.createWithHierarchy({
124
- name: "Action Figures",
125
- slug: "action-figures",
126
- categoryType: "category",
127
- isActive: true,
128
- isBrand: false,
129
- isSearchable: true,
130
- order: 1,
131
- display: {},
132
- seo: {},
133
- });
134
- expect(result.isLeaf).toBe(true);
135
- });
136
- it("calls db.collection.doc.set to persist the document", async () => {
137
- const createdDoc = makeCategoryDoc();
138
- mockDocRef.get.mockResolvedValue(makeSnap(createdDoc, createdDoc.id));
139
- await repo.createWithHierarchy({
140
- name: "Action Figures",
141
- slug: "action-figures",
142
- categoryType: "category",
143
- isActive: true,
144
- isBrand: false,
145
- isSearchable: true,
146
- order: 1,
147
- display: {},
148
- seo: {},
149
- });
150
- expect(mockDocRef.set).toHaveBeenCalledOnce();
151
- });
152
- it("does NOT update any parent's childrenIds when creating a root category", async () => {
153
- const createdDoc = makeCategoryDoc();
154
- mockDocRef.get.mockResolvedValue(makeSnap(createdDoc, createdDoc.id));
155
- await repo.createWithHierarchy({
156
- name: "Action Figures",
157
- slug: "action-figures",
158
- categoryType: "category",
159
- isActive: true,
160
- isBrand: false,
161
- isSearchable: true,
162
- order: 1,
163
- display: {},
164
- seo: {},
165
- });
166
- // update is only called for parent's childrenIds — should NOT be called for root
167
- expect(mockDocRef.update).not.toHaveBeenCalled();
168
- });
169
- });
170
- // ---------------------------------------------------------------------------
171
- // createWithHierarchy — child category
172
- // ---------------------------------------------------------------------------
173
- describe("CategoriesRepository.createWithHierarchy — child category", () => {
174
- const parentDoc = makeCategoryDoc({
175
- id: "category-action-figures",
176
- name: "Action Figures",
177
- tier: 0,
178
- parentIds: [],
179
- childrenIds: [],
180
- rootId: "category-action-figures",
181
- path: "action-figures",
182
- ancestors: [],
183
- });
184
- it("sets tier = parent.tier + 1 for a child category", async () => {
185
- const childDoc = makeCategoryDoc({
186
- id: "category-marvel",
187
- name: "Marvel",
188
- tier: 1,
189
- parentIds: ["category-action-figures"],
190
- });
191
- // First get: parent lookup (findById), second get: findByIdOrFail for return
192
- mockDocRef.get
193
- .mockResolvedValueOnce(makeSnap(parentDoc, "category-action-figures"))
194
- .mockResolvedValueOnce(makeSnap(childDoc, "category-marvel"));
195
- const result = await repo.createWithHierarchy({
196
- name: "Marvel",
197
- slug: "marvel",
198
- categoryType: "category",
199
- parentIds: ["category-action-figures"],
200
- isActive: true,
201
- isBrand: false,
202
- isSearchable: true,
203
- order: 1,
204
- display: {},
205
- seo: {},
206
- });
207
- expect(result.tier).toBe(1);
208
- });
209
- it("includes parentId in parentIds for a child category", async () => {
210
- const childDoc = makeCategoryDoc({
211
- id: "category-marvel",
212
- name: "Marvel",
213
- tier: 1,
214
- parentIds: ["category-action-figures"],
215
- });
216
- mockDocRef.get
217
- .mockResolvedValueOnce(makeSnap(parentDoc, "category-action-figures"))
218
- .mockResolvedValueOnce(makeSnap(childDoc, "category-marvel"));
219
- const result = await repo.createWithHierarchy({
220
- name: "Marvel",
221
- slug: "marvel",
222
- categoryType: "category",
223
- parentIds: ["category-action-figures"],
224
- isActive: true,
225
- isBrand: false,
226
- isSearchable: true,
227
- order: 1,
228
- display: {},
229
- seo: {},
230
- });
231
- expect(result.parentIds).toContain("category-action-figures");
232
- });
233
- it("updates parent's childrenIds to include the new child", async () => {
234
- const childDoc = makeCategoryDoc({
235
- id: "category-marvel",
236
- name: "Marvel",
237
- tier: 1,
238
- parentIds: ["category-action-figures"],
239
- });
240
- mockDocRef.get
241
- .mockResolvedValueOnce(makeSnap(parentDoc, "category-action-figures"))
242
- .mockResolvedValueOnce(makeSnap(childDoc, "category-marvel"));
243
- await repo.createWithHierarchy({
244
- name: "Marvel",
245
- slug: "marvel",
246
- categoryType: "category",
247
- parentIds: ["category-action-figures"],
248
- isActive: true,
249
- isBrand: false,
250
- isSearchable: true,
251
- order: 1,
252
- display: {},
253
- seo: {},
254
- });
255
- // Should call update on parent — childrenIds gets the new child's ID appended
256
- expect(mockDocRef.update).toHaveBeenCalledWith(expect.objectContaining({
257
- childrenIds: expect.any(Array),
258
- isLeaf: false,
259
- }));
260
- });
261
- it("sets isLeaf: false on parent after adding child", async () => {
262
- const childDoc = makeCategoryDoc({
263
- id: "category-marvel",
264
- name: "Marvel",
265
- tier: 1,
266
- parentIds: ["category-action-figures"],
267
- });
268
- mockDocRef.get
269
- .mockResolvedValueOnce(makeSnap(parentDoc, "category-action-figures"))
270
- .mockResolvedValueOnce(makeSnap(childDoc, "category-marvel"));
271
- await repo.createWithHierarchy({
272
- name: "Marvel",
273
- slug: "marvel",
274
- categoryType: "category",
275
- parentIds: ["category-action-figures"],
276
- isActive: true,
277
- isBrand: false,
278
- isSearchable: true,
279
- order: 1,
280
- display: {},
281
- seo: {},
282
- });
283
- const updateArg = mockDocRef.update.mock.calls[0][0];
284
- expect(updateArg.isLeaf).toBe(false);
285
- });
286
- });
287
- // ---------------------------------------------------------------------------
288
- // getRootCategories
289
- // ---------------------------------------------------------------------------
290
- describe("CategoriesRepository.getRootCategories", () => {
291
- it("queries tier == 0 and isActive == true", async () => {
292
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
293
- await repo.getRootCategories();
294
- expect(mockCollection.where).toHaveBeenCalledWith("tier", "==", 0);
295
- expect(mockQuery.where).toHaveBeenCalledWith("isActive", "==", true);
296
- });
297
- it("orders by order asc", async () => {
298
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
299
- await repo.getRootCategories();
300
- expect(mockQuery.orderBy).toHaveBeenCalledWith("order", "asc");
301
- });
302
- it("excludes categories with isBrand: true", async () => {
303
- const regularCat = makeCategoryDoc({ id: "cat-1", isBrand: false, tier: 0 });
304
- const brandCat = makeCategoryDoc({ id: "cat-brand", isBrand: true, tier: 0 });
305
- mockQuery.get.mockResolvedValue(makeQuerySnap([
306
- { id: "cat-1", data: regularCat },
307
- { id: "cat-brand", data: brandCat },
308
- ]));
309
- const results = await repo.getRootCategories();
310
- expect(results.every((c) => !c.isBrand)).toBe(true);
311
- expect(results.some((c) => c.id === "cat-1")).toBe(true);
312
- expect(results.some((c) => c.id === "cat-brand")).toBe(false);
313
- });
314
- it("returns empty array when no root categories exist", async () => {
315
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
316
- const results = await repo.getRootCategories();
317
- expect(results).toEqual([]);
318
- });
319
- });
320
- // ---------------------------------------------------------------------------
321
- // getLeafCategories
322
- // ---------------------------------------------------------------------------
323
- describe("CategoriesRepository.getLeafCategories", () => {
324
- it("queries isLeaf == true and isActive == true", async () => {
325
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
326
- await repo.getLeafCategories();
327
- expect(mockCollection.where).toHaveBeenCalledWith("isLeaf", "==", true);
328
- expect(mockQuery.where).toHaveBeenCalledWith("isActive", "==", true);
329
- });
330
- it("limits to 500 documents", async () => {
331
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
332
- await repo.getLeafCategories();
333
- expect(mockQuery.limit).toHaveBeenCalledWith(500);
334
- });
335
- it("returns matching leaf categories", async () => {
336
- const leaf = makeCategoryDoc({ id: "cat-leaf", isLeaf: true, isActive: true });
337
- mockQuery.get.mockResolvedValue(makeQuerySnap([{ id: "cat-leaf", data: leaf }]));
338
- const results = await repo.getLeafCategories();
339
- expect(results).toHaveLength(1);
340
- expect(results[0].isLeaf).toBe(true);
341
- });
342
- });
343
- // ---------------------------------------------------------------------------
344
- // toggleFeatured
345
- // ---------------------------------------------------------------------------
346
- describe("CategoriesRepository.toggleFeatured", () => {
347
- it("throws DatabaseError when totalItemCount < MIN_ITEMS_FOR_FEATURED", async () => {
348
- const cat = makeCategoryDoc({
349
- id: "cat-sparse",
350
- metrics: {
351
- productCount: 0,
352
- productIds: [],
353
- auctionCount: 0,
354
- auctionIds: [],
355
- totalProductCount: 0,
356
- totalAuctionCount: 0,
357
- totalItemCount: MIN_ITEMS_FOR_FEATURED - 1,
358
- lastUpdated: new Date(),
359
- },
360
- });
361
- // findByIdOrFail call + return value at end
362
- mockDocRef.get
363
- .mockResolvedValueOnce(makeSnap(cat, "cat-sparse"))
364
- .mockResolvedValueOnce(makeSnap(cat, "cat-sparse"));
365
- await expect(repo.toggleFeatured("cat-sparse", true)).rejects.toThrow(/at least/i);
366
- });
367
- it("throws when totalItemCount is exactly 0", async () => {
368
- const cat = makeCategoryDoc({
369
- id: "cat-empty",
370
- metrics: {
371
- productCount: 0,
372
- productIds: [],
373
- auctionCount: 0,
374
- auctionIds: [],
375
- totalProductCount: 0,
376
- totalAuctionCount: 0,
377
- totalItemCount: 0,
378
- lastUpdated: new Date(),
379
- },
380
- });
381
- mockDocRef.get
382
- .mockResolvedValueOnce(makeSnap(cat, "cat-empty"))
383
- .mockResolvedValueOnce(makeSnap(cat, "cat-empty"));
384
- await expect(repo.toggleFeatured("cat-empty", true)).rejects.toThrow();
385
- });
386
- it("allows featuring when totalItemCount >= MIN_ITEMS_FOR_FEATURED", async () => {
387
- const cat = makeCategoryDoc({
388
- id: "cat-rich",
389
- isFeatured: false,
390
- metrics: {
391
- productCount: MIN_ITEMS_FOR_FEATURED,
392
- productIds: [],
393
- auctionCount: 0,
394
- auctionIds: [],
395
- totalProductCount: MIN_ITEMS_FOR_FEATURED,
396
- totalAuctionCount: 0,
397
- totalItemCount: MIN_ITEMS_FOR_FEATURED,
398
- lastUpdated: new Date(),
399
- },
400
- });
401
- const featured = { ...cat, isFeatured: true };
402
- mockDocRef.get
403
- .mockResolvedValueOnce(makeSnap(cat, "cat-rich"))
404
- .mockResolvedValueOnce(makeSnap(featured, "cat-rich"));
405
- const result = await repo.toggleFeatured("cat-rich", true);
406
- expect(result.isFeatured).toBe(true);
407
- expect(mockDocRef.update).toHaveBeenCalledWith(expect.objectContaining({ isFeatured: true }));
408
- });
409
- it("allows UN-featuring regardless of totalItemCount (no guard when featured=false)", async () => {
410
- const cat = makeCategoryDoc({
411
- id: "cat-unfeature",
412
- isFeatured: true,
413
- metrics: {
414
- productCount: 0,
415
- productIds: [],
416
- auctionCount: 0,
417
- auctionIds: [],
418
- totalProductCount: 0,
419
- totalAuctionCount: 0,
420
- totalItemCount: 0,
421
- lastUpdated: new Date(),
422
- },
423
- });
424
- const unfeatured = { ...cat, isFeatured: false };
425
- mockDocRef.get
426
- .mockResolvedValueOnce(makeSnap(cat, "cat-unfeature"))
427
- .mockResolvedValueOnce(makeSnap(unfeatured, "cat-unfeature"));
428
- const result = await repo.toggleFeatured("cat-unfeature", false);
429
- expect(result.isFeatured).toBe(false);
430
- expect(mockDocRef.update).toHaveBeenCalledWith(expect.objectContaining({ isFeatured: false }));
431
- });
432
- });
433
- // ---------------------------------------------------------------------------
434
- // moveCategory
435
- // ---------------------------------------------------------------------------
436
- describe("CategoriesRepository.moveCategory", () => {
437
- const oldParent = makeCategoryDoc({
438
- id: "cat-old-parent",
439
- name: "Old Parent",
440
- tier: 0,
441
- parentIds: [],
442
- childrenIds: ["cat-child"],
443
- rootId: "cat-old-parent",
444
- });
445
- const newParent = makeCategoryDoc({
446
- id: "cat-new-parent",
447
- name: "New Parent",
448
- tier: 0,
449
- parentIds: [],
450
- childrenIds: [],
451
- rootId: "cat-new-parent",
452
- });
453
- const childCat = makeCategoryDoc({
454
- id: "cat-child",
455
- name: "Child",
456
- tier: 1,
457
- parentIds: ["cat-old-parent"],
458
- childrenIds: [],
459
- rootId: "cat-old-parent",
460
- });
461
- it("removes the category from old parent's childrenIds via batch", async () => {
462
- // findByIdOrFail(categoryId) → child
463
- // findByIdOrFail(newParentId) → new parent
464
- // findById(oldParentId) → old parent (for isLeaf check)
465
- // findByIdOrFail(categoryId) → child (return value)
466
- mockDocRef.get
467
- .mockResolvedValueOnce(makeSnap(childCat, "cat-child"))
468
- .mockResolvedValueOnce(makeSnap(newParent, "cat-new-parent"))
469
- .mockResolvedValueOnce(makeSnap(oldParent, "cat-old-parent"))
470
- .mockResolvedValueOnce(makeSnap(childCat, "cat-child"));
471
- await repo.moveCategory({
472
- categoryId: "cat-child",
473
- newParentId: "cat-new-parent",
474
- });
475
- // batch.update called for: category itself, old parent, new parent
476
- const updateCalls = mockBatch.update.mock.calls;
477
- const oldParentUpdate = updateCalls.find(([, data]) => data["childrenIds"] !== undefined && Array.isArray(data["childrenIds"]));
478
- expect(oldParentUpdate).toBeDefined();
479
- });
480
- it("adds the category to new parent's childrenIds via batch", async () => {
481
- mockDocRef.get
482
- .mockResolvedValueOnce(makeSnap(childCat, "cat-child"))
483
- .mockResolvedValueOnce(makeSnap(newParent, "cat-new-parent"))
484
- .mockResolvedValueOnce(makeSnap(oldParent, "cat-old-parent"))
485
- .mockResolvedValueOnce(makeSnap(childCat, "cat-child"));
486
- await repo.moveCategory({
487
- categoryId: "cat-child",
488
- newParentId: "cat-new-parent",
489
- });
490
- const updateCalls = mockBatch.update.mock.calls;
491
- const newParentUpdate = updateCalls.find(([, data]) => data.isLeaf === false);
492
- expect(newParentUpdate).toBeDefined();
493
- });
494
- it("commits the batch after all updates", async () => {
495
- mockDocRef.get
496
- .mockResolvedValueOnce(makeSnap(childCat, "cat-child"))
497
- .mockResolvedValueOnce(makeSnap(newParent, "cat-new-parent"))
498
- .mockResolvedValueOnce(makeSnap(oldParent, "cat-old-parent"))
499
- .mockResolvedValueOnce(makeSnap(childCat, "cat-child"));
500
- await repo.moveCategory({
501
- categoryId: "cat-child",
502
- newParentId: "cat-new-parent",
503
- });
504
- expect(mockBatch.commit).toHaveBeenCalledOnce();
505
- });
506
- it("throws DatabaseError when moving a category to itself (circular)", async () => {
507
- mockDocRef.get.mockResolvedValueOnce(makeSnap(childCat, "cat-child"));
508
- await expect(repo.moveCategory({ categoryId: "cat-child", newParentId: "cat-child" })).rejects.toThrow(/circular|invalid/i);
509
- });
510
- it("marks old parent as isLeaf: true when it has exactly 1 child (the one being moved)", async () => {
511
- const oldParentWith1Child = { ...oldParent, childrenIds: ["cat-child"] };
512
- mockDocRef.get
513
- .mockResolvedValueOnce(makeSnap(childCat, "cat-child"))
514
- .mockResolvedValueOnce(makeSnap(newParent, "cat-new-parent"))
515
- .mockResolvedValueOnce(makeSnap(oldParentWith1Child, "cat-old-parent"))
516
- .mockResolvedValueOnce(makeSnap(childCat, "cat-child"));
517
- await repo.moveCategory({
518
- categoryId: "cat-child",
519
- newParentId: "cat-new-parent",
520
- });
521
- const updateCalls = mockBatch.update.mock.calls;
522
- const leafUpdate = updateCalls.find(([, data]) => data.isLeaf === true);
523
- expect(leafUpdate).toBeDefined();
524
- });
525
- });
526
- // ---------------------------------------------------------------------------
527
- // buildTree
528
- // ---------------------------------------------------------------------------
529
- describe("CategoriesRepository.buildTree", () => {
530
- it("fetches all active non-brand categories ordered by tier then order", async () => {
531
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
532
- await repo.buildTree();
533
- expect(mockCollection.where).toHaveBeenCalledWith("isActive", "==", true);
534
- expect(mockQuery.orderBy).toHaveBeenCalledWith("tier", "asc");
535
- });
536
- it("returns an empty array when there are no categories", async () => {
537
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
538
- const result = await repo.buildTree();
539
- expect(result).toEqual([]);
540
- });
541
- it("builds nested tree correctly from flat category list", async () => {
542
- const root = makeCategoryDoc({
543
- id: "cat-root",
544
- name: "Root",
545
- tier: 0,
546
- parentIds: [],
547
- rootId: "cat-root",
548
- childrenIds: ["cat-child"],
549
- isBrand: false,
550
- });
551
- const child = makeCategoryDoc({
552
- id: "cat-child",
553
- name: "Child",
554
- tier: 1,
555
- parentIds: ["cat-root"],
556
- rootId: "cat-root",
557
- childrenIds: [],
558
- isBrand: false,
559
- });
560
- mockQuery.get.mockResolvedValue(makeQuerySnap([
561
- { id: "cat-root", data: root },
562
- { id: "cat-child", data: child },
563
- ]));
564
- const tree = await repo.buildTree();
565
- // CategoryTreeNode has { category, children, depth }, not a top-level id
566
- expect(tree.length).toBeGreaterThanOrEqual(1);
567
- const rootNode = tree.find((n) => n.category.id === "cat-root");
568
- expect(rootNode).toBeDefined();
569
- });
570
- it("filters out isBrand categories from the global tree", async () => {
571
- const brand = makeCategoryDoc({
572
- id: "cat-brand",
573
- name: "Brand Category",
574
- tier: 0,
575
- parentIds: [],
576
- isBrand: true,
577
- });
578
- mockQuery.get.mockResolvedValue(makeQuerySnap([{ id: "cat-brand", data: brand }]));
579
- const tree = await repo.buildTree();
580
- expect(tree.find((n) => n.category.id === "cat-brand")).toBeUndefined();
581
- });
582
- });
583
- // ---------------------------------------------------------------------------
584
- // listByType
585
- // ---------------------------------------------------------------------------
586
- describe("CategoriesRepository.listByType", () => {
587
- it("queries categoryType == the requested type", async () => {
588
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
589
- await repo.listByType("sublisting");
590
- expect(mockCollection.where).toHaveBeenCalledWith("categoryType", "==", "sublisting");
591
- });
592
- it("returns only documents matching the requested categoryType", async () => {
593
- const sublisting = makeCategoryDoc({
594
- id: "sublisting-holos",
595
- categoryType: "sublisting",
596
- });
597
- mockQuery.get.mockResolvedValue(makeQuerySnap([{ id: "sublisting-holos", data: sublisting }]));
598
- const results = await repo.listByType("sublisting");
599
- expect(results).toHaveLength(1);
600
- expect(results[0].id).toBe("sublisting-holos");
601
- });
602
- it("applies activeOnly filter when opts.activeOnly is true", async () => {
603
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
604
- await repo.listByType("brand", { activeOnly: true });
605
- expect(mockQuery.where).toHaveBeenCalledWith("isActive", "==", true);
606
- });
607
- it("does NOT apply activeOnly filter by default", async () => {
608
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
609
- await repo.listByType("brand");
610
- // where on query should not have been called for isActive
611
- const queryWhereCalls = mockQuery.where.mock.calls;
612
- const isActiveCall = queryWhereCalls.find(([field]) => field === "isActive");
613
- expect(isActiveCall).toBeUndefined();
614
- });
615
- it("applies limit when opts.limit is set", async () => {
616
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
617
- await repo.listByType("bundle", { limit: 10 });
618
- expect(mockQuery.limit).toHaveBeenCalledWith(10);
619
- });
620
- it("returns empty array when no documents match the type", async () => {
621
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
622
- const results = await repo.listByType("bundle");
623
- expect(results).toEqual([]);
624
- });
625
- });
626
- // ---------------------------------------------------------------------------
627
- // findBySlugAndType
628
- // ---------------------------------------------------------------------------
629
- describe("CategoriesRepository.findBySlugAndType", () => {
630
- it("queries by slug field", async () => {
631
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
632
- await repo.findBySlugAndType("action-figures");
633
- expect(mockCollection.where).toHaveBeenCalledWith("slug", "==", "action-figures");
634
- });
635
- it("limits to 1 result", async () => {
636
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
637
- await repo.findBySlugAndType("action-figures");
638
- expect(mockQuery.limit).toHaveBeenCalledWith(1);
639
- });
640
- it("returns null when no document matches the slug", async () => {
641
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
642
- const result = await repo.findBySlugAndType("nonexistent-slug");
643
- expect(result).toBeNull();
644
- });
645
- it("returns the category document when slug matches", async () => {
646
- const cat = makeCategoryDoc({ id: "category-action-figures", slug: "action-figures" });
647
- mockQuery.get.mockResolvedValue(makeQuerySnap([{ id: "category-action-figures", data: cat }]));
648
- const result = await repo.findBySlugAndType("action-figures");
649
- expect(result).not.toBeNull();
650
- expect(result?.slug).toBe("action-figures");
651
- });
652
- it("adds categoryType filter when type argument is provided", async () => {
653
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
654
- await repo.findBySlugAndType("some-brand", "brand");
655
- expect(mockQuery.where).toHaveBeenCalledWith("categoryType", "==", "brand");
656
- });
657
- it("does NOT add categoryType filter when type is not provided", async () => {
658
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
659
- await repo.findBySlugAndType("action-figures");
660
- const queryWhereCalls = mockQuery.where.mock.calls;
661
- const typeFilterCall = queryWhereCalls.find(([field]) => field === "categoryType");
662
- expect(typeFilterCall).toBeUndefined();
663
- });
664
- });
665
- // ---------------------------------------------------------------------------
666
- // getChildren
667
- // ---------------------------------------------------------------------------
668
- describe("CategoriesRepository.getChildren", () => {
669
- it("queries parentIds array-contains the given parentId", async () => {
670
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
671
- await repo.getChildren("category-action-figures");
672
- expect(mockCollection.where).toHaveBeenCalledWith("parentIds", "array-contains", "category-action-figures");
673
- });
674
- it("limits to 100 documents", async () => {
675
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
676
- await repo.getChildren("category-action-figures");
677
- expect(mockQuery.limit).toHaveBeenCalledWith(100);
678
- });
679
- it("filters in-memory to return only DIRECT children (parentIds last element === parentId)", async () => {
680
- // Direct child: parentIds last item = parentId
681
- const directChild = makeCategoryDoc({
682
- id: "cat-direct",
683
- parentIds: ["category-action-figures"],
684
- });
685
- // Non-direct descendant: parentIds last item is something else (it's a grandchild)
686
- const grandChild = makeCategoryDoc({
687
- id: "cat-grandchild",
688
- parentIds: ["category-action-figures", "cat-direct"],
689
- });
690
- mockQuery.get.mockResolvedValue(makeQuerySnap([
691
- { id: "cat-direct", data: directChild },
692
- { id: "cat-grandchild", data: grandChild },
693
- ]));
694
- const results = await repo.getChildren("category-action-figures");
695
- expect(results.map((r) => r.id)).toContain("cat-direct");
696
- expect(results.map((r) => r.id)).not.toContain("cat-grandchild");
697
- });
698
- it("returns empty array when no children exist", async () => {
699
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
700
- const results = await repo.getChildren("cat-leaf-node");
701
- expect(results).toEqual([]);
702
- });
703
- });
704
- // ---------------------------------------------------------------------------
705
- // updateMetricsInBatch (synchronous batch staging)
706
- // ---------------------------------------------------------------------------
707
- describe("CategoriesRepository.updateMetricsInBatch", () => {
708
- it("stages a batch.update for the direct category", () => {
709
- const batch = {
710
- update: vi.fn(),
711
- commit: vi.fn().mockResolvedValue(undefined),
712
- };
713
- repo.updateMetricsInBatch(batch, "category-action-figures", [], 1, 0);
714
- expect(batch.update).toHaveBeenCalledOnce();
715
- });
716
- it("stages batch.update for every ancestor in parentIds", () => {
717
- const batch = {
718
- update: vi.fn(),
719
- commit: vi.fn().mockResolvedValue(undefined),
720
- };
721
- repo.updateMetricsInBatch(batch, "cat-child", ["cat-root", "cat-parent"], 1, 0);
722
- // 1 for direct + 2 for ancestors = 3 total
723
- expect(batch.update).toHaveBeenCalledTimes(3);
724
- });
725
- it("does NOT call batch.commit (caller is responsible)", () => {
726
- const batch = {
727
- update: vi.fn(),
728
- commit: vi.fn().mockResolvedValue(undefined),
729
- };
730
- repo.updateMetricsInBatch(batch, "cat-child", [], 1, 0);
731
- expect(batch.commit).not.toHaveBeenCalled();
732
- });
733
- it("includes productId in arrayUnion for productIds field when productDelta > 0", () => {
734
- const capturedUpdates = [];
735
- const batch = {
736
- update: vi.fn((_ref, data) => capturedUpdates.push(data)),
737
- commit: vi.fn().mockResolvedValue(undefined),
738
- };
739
- repo.updateMetricsInBatch(batch, "cat-child", [], 1, 0, "product-test-123");
740
- const directUpdate = capturedUpdates[0];
741
- // arrayUnion mock returns args as array
742
- expect(directUpdate["metrics.productIds"]).toEqual(["product-test-123"]);
743
- });
744
- });
745
- // ---------------------------------------------------------------------------
746
- // getCategoryBySlug
747
- // ---------------------------------------------------------------------------
748
- describe("CategoriesRepository.getCategoryBySlug", () => {
749
- it("queries slug == given slug and limits to 1", async () => {
750
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
751
- await repo.getCategoryBySlug("action-figures");
752
- expect(mockCollection.where).toHaveBeenCalledWith("slug", "==", "action-figures");
753
- expect(mockQuery.limit).toHaveBeenCalledWith(1);
754
- });
755
- it("returns null when no category matches the slug", async () => {
756
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
757
- const result = await repo.getCategoryBySlug("nonexistent");
758
- expect(result).toBeNull();
759
- });
760
- it("returns the category when slug matches", async () => {
761
- const cat = makeCategoryDoc({ id: "cat-af", slug: "action-figures" });
762
- mockQuery.get.mockResolvedValue(makeQuerySnap([{ id: "cat-af", data: cat }]));
763
- const result = await repo.getCategoryBySlug("action-figures");
764
- expect(result?.slug).toBe("action-figures");
765
- });
766
- });
767
- // ---------------------------------------------------------------------------
768
- // findActiveBrands
769
- // ---------------------------------------------------------------------------
770
- describe("CategoriesRepository.findActiveBrands", () => {
771
- it("queries categoryType == brand and isActive == true", async () => {
772
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
773
- await repo.findActiveBrands();
774
- expect(mockCollection.where).toHaveBeenCalledWith("categoryType", "==", "brand");
775
- expect(mockQuery.where).toHaveBeenCalledWith("isActive", "==", true);
776
- });
777
- it("orders by order asc", async () => {
778
- mockQuery.get.mockResolvedValue(makeQuerySnap([]));
779
- await repo.findActiveBrands();
780
- expect(mockQuery.orderBy).toHaveBeenCalledWith("order", "asc");
781
- });
782
- it("returns active brand categories", async () => {
783
- const brand = makeCategoryDoc({
784
- id: "cat-bandai",
785
- categoryType: "brand",
786
- isActive: true,
787
- });
788
- mockQuery.get.mockResolvedValue(makeQuerySnap([{ id: "cat-bandai", data: brand }]));
789
- const results = await repo.findActiveBrands();
790
- expect(results).toHaveLength(1);
791
- expect(results[0].categoryType).toBe("brand");
792
- });
793
- });
794
- // ---------------------------------------------------------------------------
795
- // generateSublistingId
796
- // ---------------------------------------------------------------------------
797
- describe("CategoriesRepository.generateSublistingId", () => {
798
- it("returns sublisting- prefixed slug from name", () => {
799
- expect(repo.generateSublistingId("Holo Cards")).toBe("sublisting-holo-cards");
800
- });
801
- it("does not double-prefix if name already starts with sublisting-", () => {
802
- expect(repo.generateSublistingId("sublisting-holos")).toBe("sublisting-holos");
803
- });
804
- it("converts uppercase to lowercase", () => {
805
- expect(repo.generateSublistingId("POKEMON")).toBe("sublisting-pokemon");
806
- });
807
- it("replaces non-alphanumeric chars with hyphens", () => {
808
- expect(repo.generateSublistingId("First Edition!")).toBe("sublisting-first-edition");
809
- });
810
- it("trims leading and trailing hyphens", () => {
811
- expect(repo.generateSublistingId(" holos ")).toBe("sublisting-holos");
812
- });
813
- });