@mohasinac/appkit 4.53.1 → 4.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.build-stamp.json +3 -3
- package/dist/_internal/client/theme/ThemeProvider.js +15 -1
- package/dist/_internal/server/features/auth/capabilities.js +7 -5
- package/dist/_internal/server/features/categories/price-guidance-resolve.d.ts +66 -0
- package/dist/_internal/server/features/categories/price-guidance-resolve.js +138 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +22 -6
- package/dist/_internal/server/features/checkout/actions.js +96 -51
- package/dist/_internal/server/features/checkout/index.d.ts +1 -1
- package/dist/_internal/server/features/checkout/index.js +1 -1
- package/dist/_internal/server/features/checkout/supplier-identity.js +28 -6
- package/dist/_internal/server/features/orders/adapters.js +1 -3
- package/dist/_internal/server/features/price-index/market.d.ts +57 -0
- package/dist/_internal/server/features/price-index/market.js +120 -0
- package/dist/_internal/server/features/products/list-public.d.ts +12 -0
- package/dist/_internal/server/features/products/list-public.js +10 -1
- package/dist/_internal/server/features/products/listing-tab-counts.d.ts +25 -1
- package/dist/_internal/server/features/products/listing-tab-counts.js +184 -10
- package/dist/_internal/server/features/search/index-build/sources.js +43 -2
- package/dist/_internal/server/features/site-settings/adapters.js +1 -1
- package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
- package/dist/_internal/server/features/stores/adapters.js +0 -1
- package/dist/_internal/server/features/stores/tabs.d.ts +7 -2
- package/dist/_internal/server/features/stores/tabs.js +5 -3
- package/dist/_internal/server/jobs/core/analyticsAlertEvaluate.js +2 -5
- package/dist/_internal/server/jobs/core/jobRunners.js +0 -10
- package/dist/_internal/server/jobs/core/onOrderCreate.js +10 -104
- package/dist/_internal/server/jobs/core/onOrderStatusChange.d.ts +0 -2
- package/dist/_internal/server/jobs/core/onOrderStatusChange.js +0 -1
- package/dist/_internal/server/jobs/core/onScamReportCreate.js +0 -1
- package/dist/_internal/server/jobs/core/onScamReportRejected.js +0 -1
- package/dist/_internal/server/jobs/core/onScamReportVerified.js +0 -1
- package/dist/_internal/server/jobs/core/paymentWindowTimeout.js +0 -1
- package/dist/_internal/server/jobs/core/pendingOrderTimeout.js +0 -1
- package/dist/_internal/server/notifications/channel-health.d.ts +7 -3
- package/dist/_internal/server/notifications/channel-health.js +2 -2
- package/dist/_internal/server/notifications/send-guard.d.ts +1 -1
- package/dist/_internal/server/notifications/send-guard.js +2 -4
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +128 -28
- package/dist/_internal/shared/checkout/order-math.d.ts +1 -1
- package/dist/_internal/shared/checkout/order-math.js +1 -1
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +1 -1
- package/dist/_internal/shared/features/checkout/config.d.ts +0 -2
- package/dist/_internal/shared/features/checkout/config.js +0 -2
- package/dist/_internal/shared/features/messaging/config.d.ts +7 -5
- package/dist/_internal/shared/features/messaging/config.js +1 -4
- package/dist/_internal/shared/features/site-settings/fees.d.ts +0 -2
- package/dist/_internal/shared/features/site-settings/fees.js +0 -2
- package/dist/_internal/shared/features/site-settings/supplier-of-record.d.ts +56 -0
- package/dist/_internal/shared/features/site-settings/supplier-of-record.js +57 -0
- package/dist/_internal/shared/fees/calculator.d.ts +0 -8
- package/dist/_internal/shared/fees/calculator.js +0 -7
- package/dist/_internal/shared/listing-types/tiers.d.ts +94 -0
- package/dist/_internal/shared/listing-types/tiers.js +150 -0
- package/dist/_internal/shared/search/match.js +28 -2
- package/dist/cli/index.js +0 -2
- package/dist/client.d.ts +25 -4
- package/dist/client.js +36 -5
- package/dist/constants/api-endpoints.d.ts +28 -15
- package/dist/constants/api-endpoints.js +14 -8
- package/dist/constants/field-names.d.ts +1 -0
- package/dist/constants/field-names.js +1 -0
- package/dist/constants/notification-types.d.ts +1 -1
- package/dist/constants/notification-types.js +1 -1
- package/dist/core/integration-keys.d.ts +5 -5
- package/dist/core/integration-keys.js +21 -10
- package/dist/features/about/components/FeesView.js +0 -6
- package/dist/features/about/components/GuidesHubView.js +15 -2
- package/dist/features/account/components/NotificationPreferencesPanel.js +3 -4
- package/dist/features/account/components/UserOrdersView.js +26 -7
- package/dist/features/account/types/index.d.ts +0 -2
- package/dist/features/addresses/utils/postal-autofill.d.ts +39 -0
- package/dist/features/addresses/utils/postal-autofill.js +54 -0
- package/dist/features/admin/actions/notification-actions.d.ts +2 -8
- package/dist/features/admin/actions/notification-actions.js +9 -104
- package/dist/features/admin/components/AdminGuideHubView.js +1 -8
- package/dist/features/admin/components/AdminOrderEditorView.d.ts +1 -1
- package/dist/features/admin/components/AdminOrdersView.js +0 -2
- package/dist/features/admin/components/AdminSectionsView.js +3 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +22 -68
- package/dist/features/admin/components/AdminStoreEditorView.js +72 -34
- package/dist/features/admin/components/OwnerQuickActions.d.ts +29 -0
- package/dist/features/admin/components/OwnerQuickActions.js +142 -0
- package/dist/features/admin/components/sections/adminSectionsTypes.js +13 -4
- package/dist/features/admin/components/sections/icon-options.d.ts +21 -0
- package/dist/features/admin/components/sections/icon-options.js +23 -0
- package/dist/features/admin/components/sections/sectionTemplates.js +4 -1
- package/dist/features/admin/constants/site-settings-tabs.d.ts +7 -12
- package/dist/features/admin/constants/site-settings-tabs.js +6 -12
- package/dist/features/admin/repository/site-settings.repository.js +1 -1
- package/dist/features/admin/schemas/admin-editor-forms.d.ts +1 -1
- package/dist/features/admin/schemas/admin-editor-forms.js +4 -1
- package/dist/features/admin/schemas/admin-user-form.d.ts +0 -61
- package/dist/features/admin/schemas/admin-user-form.js +3 -44
- package/dist/features/admin/schemas/firestore.d.ts +28 -54
- package/dist/features/admin/schemas/firestore.js +40 -18
- package/dist/features/auctions/components/AuctionDetailPageView.js +12 -10
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -2
- package/dist/features/auth/checkout-value-otp.d.ts +1 -1
- package/dist/features/auth/checkout-value-otp.js +1 -1
- package/dist/features/auth/permissions/constants.d.ts +29 -2
- package/dist/features/auth/permissions/constants.js +67 -1
- package/dist/features/blog/components/BlogFeaturedCard.d.ts +11 -1
- package/dist/features/blog/components/BlogFeaturedCard.js +9 -2
- package/dist/features/cart/components/CartDrawer.js +3 -2
- package/dist/features/cart/components/CartGroupLineRow.js +2 -1
- package/dist/features/cart/components/CartPriceBreakdown.d.ts +0 -2
- package/dist/features/cart/components/CartPriceBreakdown.js +1 -1
- package/dist/features/cart/components/StoreAddonsPicker.d.ts +2 -5
- package/dist/features/cart/components/StoreAddonsPicker.js +4 -5
- package/dist/features/cart/hooks/useAddToCart.js +10 -5
- package/dist/features/cart/repository/cart.repository.js +1 -2
- package/dist/features/cart/schemas/firestore.d.ts +1 -2
- package/dist/features/cart/utils/pending-ops.d.ts +11 -1
- package/dist/features/cart/utils/pending-ops.js +14 -2
- package/dist/features/categories/api/[id]/price-guidance/route.js +1 -24
- package/dist/features/categories/components/BrandDetailPageView.js +15 -6
- package/dist/features/categories/components/BrandDetailTabs.d.ts +7 -1
- package/dist/features/categories/components/BrandDetailTabs.js +18 -3
- package/dist/features/categories/components/BundleCollage.js +3 -2
- package/dist/features/categories/components/BundleDetailView.js +2 -1
- package/dist/features/categories/components/BundleItemsPicker.js +3 -4
- package/dist/features/categories/components/CategoryDetailPageView.js +19 -8
- package/dist/features/categories/components/CategoryDetailTabs.d.ts +7 -1
- package/dist/features/categories/components/CategoryDetailTabs.js +29 -7
- package/dist/features/categories/components/CategoryGrid.d.ts +11 -1
- package/dist/features/categories/components/CategoryGrid.js +9 -2
- package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +10 -5
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +2 -88
- package/dist/features/classified/components/ClassifiedDetailPageView.js +12 -2
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +12 -2
- package/dist/features/events/components/EventCard.d.ts +11 -1
- package/dist/features/events/components/EventCard.js +9 -2
- package/dist/features/grouped/components/GroupedListingDetailView.js +3 -1
- package/dist/features/homepage/components/CTABannerSection.d.ts +3 -1
- package/dist/features/homepage/components/CTABannerSection.js +6 -3
- package/dist/features/homepage/components/HeroCarousel.js +8 -6
- package/dist/features/homepage/components/MarketplaceHomepageView.js +33 -7
- package/dist/features/homepage/components/SectionCarousel.js +13 -5
- package/dist/features/homepage/components/SecurityHighlightsSection.d.ts +8 -3
- package/dist/features/homepage/components/SecurityHighlightsSection.js +2 -2
- package/dist/features/homepage/components/StatsCounterSection.d.ts +9 -4
- package/dist/features/homepage/components/StatsCounterSection.js +2 -2
- package/dist/features/homepage/components/TestimonialsCarousel.js +1 -1
- package/dist/features/homepage/components/TrustFeaturesSection.d.ts +18 -4
- package/dist/features/homepage/components/TrustFeaturesSection.js +5 -5
- package/dist/features/homepage/components/WelcomeSection.d.ts +13 -2
- package/dist/features/homepage/components/WelcomeSection.js +3 -3
- package/dist/features/homepage/components/WhatsAppCommunitySection.d.ts +28 -0
- package/dist/features/homepage/components/WhatsAppCommunitySection.js +42 -6
- package/dist/features/homepage/components/WhatsAppGlyph.d.ts +20 -0
- package/dist/features/homepage/components/WhatsAppGlyph.js +20 -0
- package/dist/features/homepage/constants/hero-carousel-styles.d.ts +8 -6
- package/dist/features/homepage/constants/hero-carousel-styles.js +8 -6
- package/dist/features/homepage/constants/section-copy.d.ts +12 -10
- package/dist/features/homepage/constants/section-copy.js +28 -6
- package/dist/features/homepage/constants/stat-icons.d.ts +12 -0
- package/dist/features/homepage/constants/stat-icons.js +17 -0
- package/dist/features/homepage/constants/trust-icon-aliases.d.ts +8 -0
- package/dist/features/homepage/constants/trust-icon-aliases.js +75 -0
- package/dist/features/homepage/lib/section-defaults.d.ts +16 -1
- package/dist/features/homepage/lib/section-defaults.js +24 -4
- package/dist/features/homepage/lib/section-renderer.js +48 -8
- package/dist/features/homepage/schemas/firestore.d.ts +18 -1
- package/dist/features/layout/AppLayoutShell.js +2 -1
- package/dist/features/layout/BottomActions.d.ts +1 -0
- package/dist/features/layout/BottomActions.js +330 -0
- package/dist/features/layout/BottomChrome.d.ts +45 -0
- package/dist/features/layout/BottomChrome.js +5 -17
- package/dist/features/layout/SideActionDock.js +36 -13
- package/dist/features/layout/index.d.ts +2 -7
- package/dist/features/layout/index.js +7 -7
- package/dist/features/layout/useIsDesktop.d.ts +36 -0
- package/dist/features/layout/useIsDesktop.js +48 -0
- package/dist/features/live/components/LiveItemDetailPageView.js +12 -2
- package/dist/features/orders/actions/refund-actions.js +0 -1
- package/dist/features/orders/components/OrderAddonBadges.d.ts +1 -3
- package/dist/features/orders/components/OrderAddonBadges.js +3 -4
- package/dist/features/orders/components/OrderPaymentSummary.js +15 -2
- package/dist/features/orders/components/YourPurchaseStrip.d.ts +24 -0
- package/dist/features/orders/components/YourPurchaseStrip.js +77 -0
- package/dist/features/orders/components/index.d.ts +2 -1
- package/dist/features/orders/components/index.js +1 -1
- package/dist/features/orders/repository/orders.repository.d.ts +0 -8
- package/dist/features/orders/repository/orders.repository.js +0 -2
- package/dist/features/orders/schemas/firestore.d.ts +17 -9
- package/dist/features/orders/types/index.d.ts +2 -5
- package/dist/features/orders/utils/order-announcement-message.d.ts +18 -0
- package/dist/features/orders/utils/order-announcement-message.js +16 -0
- package/dist/features/orders/utils/payment-proof-message.d.ts +20 -0
- package/dist/features/orders/utils/payment-proof-message.js +17 -0
- package/dist/features/parts/components/PartDetailPageView.js +96 -1
- package/dist/features/parts/schemas/firestore.d.ts +247 -0
- package/dist/features/parts/schemas/firestore.js +6 -6
- package/dist/features/pre-orders/components/MarketplacePreorderCard.d.ts +11 -1
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +10 -3
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +12 -10
- package/dist/features/price-index/components/PriceIndexToolView.d.ts +21 -0
- package/dist/features/price-index/components/PriceIndexToolView.js +230 -27
- package/dist/features/price-index/lookup-target.d.ts +48 -0
- package/dist/features/price-index/lookup-target.js +107 -0
- package/dist/features/products/api/[id]/route.js +8 -1
- package/dist/features/products/api/route.js +16 -4
- package/dist/features/products/components/AvailabilityScopeHint.d.ts +22 -0
- package/dist/features/products/components/AvailabilityScopeHint.js +27 -0
- package/dist/features/products/components/CompareOverlay.d.ts +2 -1
- package/dist/features/products/components/CompareOverlay.js +2 -1
- package/dist/features/products/components/GroupSettingsPanel.js +2 -1
- package/dist/features/products/components/InteractiveProductCard.d.ts +7 -1
- package/dist/features/products/components/InteractiveProductCard.js +16 -4
- package/dist/features/products/components/MarketplaceBundleCard.d.ts +11 -1
- package/dist/features/products/components/MarketplaceBundleCard.js +9 -2
- package/dist/features/products/components/MarketplacePrizeDrawCard.d.ts +11 -1
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +9 -2
- package/dist/features/products/components/PrizeDrawDetailPageView.js +2 -1
- package/dist/features/products/components/ProductDetailPageView.js +34 -4
- package/dist/features/products/components/ProductGrid.d.ts +14 -1
- package/dist/features/products/components/ProductGrid.js +22 -5
- package/dist/features/products/components/ProductsIndexListing.js +2 -2
- package/dist/features/products/components/SublistingCarouselSection.js +2 -1
- package/dist/features/products/repository/products.repository.d.ts +1 -0
- package/dist/features/products/repository/products.repository.js +5 -1
- package/dist/features/products/utils/group-member-image.d.ts +9 -2
- package/dist/features/products/utils/group-member-image.js +2 -1
- package/dist/features/reviews/api/[id]/route.js +83 -23
- package/dist/features/reviews/components/PurchaseReviewAffordance.d.ts +6 -0
- package/dist/features/reviews/components/PurchaseReviewAffordance.js +42 -0
- package/dist/features/reviews/components/ReviewFormDrawer.d.ts +34 -0
- package/dist/features/reviews/components/ReviewFormDrawer.js +127 -0
- package/dist/features/reviews/components/index.d.ts +4 -0
- package/dist/features/reviews/components/index.js +2 -0
- package/dist/features/scams/schemas/index.d.ts +10 -10
- package/dist/features/search/action-index/settings-entries.js +0 -9
- package/dist/features/seller/actions/seller-actions.d.ts +1 -1
- package/dist/features/seller/actions/seller-actions.js +49 -3
- package/dist/features/seller/components/SellerPayoutSettingsView.js +30 -2
- package/dist/features/seller/components/SellerProductShell.d.ts +17 -1
- package/dist/features/seller/components/SellerProductsView.js +3 -2
- package/dist/features/seller/hooks/useStoreListingEntitlements.d.ts +8 -0
- package/dist/features/seller/hooks/useStoreListingEntitlements.js +70 -0
- package/dist/features/store-extensions/repository/store-extensions.repositories.d.ts +1 -6
- package/dist/features/store-extensions/repository/store-extensions.repositories.js +1 -10
- package/dist/features/store-extensions/schemas/firestore.d.ts +1 -17
- package/dist/features/store-extensions/schemas/firestore.js +0 -10
- package/dist/features/stores/components/InteractiveStoreCard.d.ts +11 -1
- package/dist/features/stores/components/InteractiveStoreCard.js +9 -2
- package/dist/features/stores/components/StoreAuctionsListing.js +2 -1
- package/dist/features/stores/components/StoreCapabilitiesGuideView.js +0 -1
- package/dist/features/stores/components/StoreGuideHubView.js +2 -8
- package/dist/features/stores/components/StoreSettingsGuideView.js +2 -6
- package/dist/features/stores/components/index.d.ts +0 -2
- package/dist/features/stores/components/index.js +0 -1
- package/dist/features/stores/repository/store.repository.d.ts +1 -26
- package/dist/features/stores/repository/store.repository.js +5 -60
- package/dist/features/stores/schemas/firestore.d.ts +6 -25
- package/dist/features/stores/schemas/firestore.js +6 -3
- package/dist/features/stores/schemas/index.d.ts +1 -87
- package/dist/features/stores/schemas/index.js +10 -15
- package/dist/features/tester/seed-data/authored/admin__site-system.js +0 -48
- package/dist/features/tester/seed-data/authored/buying__buying-checkout.js +0 -40
- package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +114 -2
- package/dist/features/tester/seed-data/authored/selling__quick-add-minimum-details.js +0 -16
- package/dist/features/tester/seed-data/authored/selling__seller-guide.js +1 -1
- package/dist/features/tester/seed-data/authored/selling__seller-marketing-extras.js +0 -79
- package/dist/features/tester/seed-data/authored/selling__seller-orders.js +1 -1
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +427 -69
- package/dist/index.d.ts +20 -32
- package/dist/index.js +34 -43
- package/dist/next/routing/route-map.d.ts +2 -8
- package/dist/next/routing/route-map.js +21 -4
- package/dist/providers/db-firebase/base.repository.d.ts +1 -1
- package/dist/providers/db-firebase/base.repository.js +1 -1
- package/dist/providers/payment-razorpay/index.d.ts +125 -0
- package/dist/providers/payment-razorpay/index.js +232 -0
- package/dist/providers/payment-razorpay/signature.d.ts +53 -0
- package/dist/providers/payment-razorpay/signature.js +71 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +98 -0
- package/dist/providers/shipping-shiprocket/index.js +356 -0
- package/dist/providers.d.ts +3 -0
- package/dist/providers.js +3 -0
- package/dist/react/hooks/useCanSeePrices.d.ts +0 -27
- package/dist/react/hooks/useCanSeePrices.js +25 -0
- package/dist/repositories/index.d.ts +1 -1
- package/dist/repositories/index.js +1 -1
- package/dist/schemas/registry.d.ts +10 -115
- package/dist/schemas/registry.js +1 -2
- package/dist/security/pii-encrypt.js +1 -1
- package/dist/seed/_helpers/category-forest.js +27 -0
- package/dist/seed/_helpers/category-parts-glossary-map.js +1816 -86
- package/dist/seed/_helpers/category-parts.d.ts +1 -1
- package/dist/seed/_helpers/category-parts.js +13412 -3020
- package/dist/seed/carousel-slides-seed-data.js +47 -10
- package/dist/seed/categories-seed-data.js +48 -6
- package/dist/seed/faq-seed-data.js +2 -2
- package/dist/seed/homepage-sections-seed-data.js +286 -54
- package/dist/seed/index.d.ts +1 -1
- package/dist/seed/index.js +1 -1
- package/dist/seed/manifest.d.ts +1 -1
- package/dist/seed/manifest.js +1 -2
- package/dist/seed/model-composition-seed-data.js +6 -8
- package/dist/seed/part-glossary/chunk0.d.ts +9 -0
- package/dist/seed/part-glossary/chunk0.js +35448 -0
- package/dist/seed/part-glossary/chunk1.d.ts +9 -0
- package/dist/seed/part-glossary/chunk1.js +40494 -0
- package/dist/seed/part-glossary/chunk2.d.ts +9 -0
- package/dist/seed/part-glossary/chunk2.js +51242 -0
- package/dist/seed/part-glossary/chunk3.d.ts +9 -0
- package/dist/seed/part-glossary/chunk3.js +53337 -0
- package/dist/seed/part-glossary/chunk4.d.ts +9 -0
- package/dist/seed/part-glossary/chunk4.js +51454 -0
- package/dist/seed/part-glossary-seed-data.d.ts +1 -1
- package/dist/seed/part-glossary-seed-data.js +23 -47483
- package/dist/seed/products-beyblade-x-seed-data.js +36 -1
- package/dist/seed/site-settings-seed-data.js +34 -35
- package/dist/seed/store-extensions-seed-data.d.ts +1 -2
- package/dist/seed/store-extensions-seed-data.js +1 -23
- package/dist/seed/stores-seed-data.js +0 -1
- package/dist/server-entry.d.ts +1 -1
- package/dist/server-entry.js +1 -1
- package/dist/server.d.ts +10 -10
- package/dist/server.js +24 -22
- package/dist/styles.css +392 -43
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/default-dark.js +1 -1
- package/dist/tokens/themes/default-light.js +2 -1
- package/dist/tokens/tokens.css +6 -2
- package/dist/ui/components/Button.d.ts +11 -0
- package/dist/ui/components/Button.js +11 -0
- package/dist/ui/components/Button.style.css +29 -0
- package/dist/ui/components/CarouselNav.d.ts +57 -0
- package/dist/ui/components/CarouselNav.js +25 -0
- package/dist/ui/components/CarouselNav.style.css +265 -0
- package/dist/ui/components/GatedPrice.js +30 -3
- package/dist/ui/components/GatedPrice.style.css +43 -40
- package/dist/ui/components/HorizontalScroller.d.ts +12 -1
- package/dist/ui/components/HorizontalScroller.js +43 -3
- package/dist/ui/components/ImageMosaic.d.ts +8 -1
- package/dist/ui/components/ImageMosaic.js +3 -2
- package/dist/ui/components/ImageMosaic.style.css +22 -0
- package/dist/ui/components/Layout.style.css +6 -0
- package/dist/ui/components/Semantic.d.ts +3 -2
- package/dist/ui/components/Semantic.js +1 -0
- package/dist/ui/components/Typography.d.ts +2 -0
- package/dist/ui/components/Typography.js +2 -0
- package/dist/ui/components/Typography.style.css +19 -0
- package/dist/ui/components/index.style.css +1 -0
- package/dist/ui/index.d.ts +3 -1
- package/dist/ui/index.js +4 -0
- package/package.json +3 -2
- package/scripts/seed-cli.mjs +133 -27
- package/dist/_internal/server/jobs/core/whatsappCatalogImport.d.ts +0 -27
- package/dist/_internal/server/jobs/core/whatsappCatalogImport.js +0 -172
- package/dist/_internal/server/jobs/core/whatsappNotify.d.ts +0 -35
- package/dist/_internal/server/jobs/core/whatsappNotify.js +0 -140
- package/dist/features/admin/components/AdminWhatsAppGuideView.d.ts +0 -2
- package/dist/features/admin/components/AdminWhatsAppGuideView.js +0 -35
- package/dist/features/orders/components/MarketplaceOrderCard.d.ts +0 -36
- package/dist/features/orders/components/MarketplaceOrderCard.js +0 -57
- package/dist/features/stores/components/StoreWhatsAppGuideView.d.ts +0 -3
- package/dist/features/stores/components/StoreWhatsAppGuideView.js +0 -12
- package/dist/features/whatsapp-bot/api/send-status/route.d.ts +0 -12
- package/dist/features/whatsapp-bot/api/send-status/route.js +0 -38
- package/dist/features/whatsapp-bot/api/webhook/route.d.ts +0 -12
- package/dist/features/whatsapp-bot/api/webhook/route.js +0 -43
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.d.ts +0 -6
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +0 -270
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.d.ts +0 -9
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +0 -7
- package/dist/features/whatsapp-bot/components/index.d.ts +0 -3
- package/dist/features/whatsapp-bot/components/index.js +0 -2
- package/dist/features/whatsapp-bot/helpers/payment-proof-message.d.ts +0 -14
- package/dist/features/whatsapp-bot/helpers/payment-proof-message.js +0 -17
- package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +0 -52
- package/dist/features/whatsapp-bot/helpers/whatsapp.js +0 -283
- package/dist/features/whatsapp-bot/index.d.ts +0 -3
- package/dist/features/whatsapp-bot/index.js +0 -3
- package/dist/features/whatsapp-bot/manifest.d.ts +0 -2
- package/dist/features/whatsapp-bot/manifest.js +0 -13
- package/dist/features/whatsapp-bot/messages/en.json +0 -7
- package/dist/features/whatsapp-bot/server.d.ts +0 -7
- package/dist/features/whatsapp-bot/server.js +0 -7
- package/dist/features/whatsapp-bot/types/index.d.ts +0 -126
- package/dist/features/whatsapp-bot/types/index.js +0 -1
|
@@ -254,28 +254,6 @@ export interface StoreDocument extends BaseDocument {
|
|
|
254
254
|
* than trusting that nobody adds it.
|
|
255
255
|
*/
|
|
256
256
|
returnsDirectToSeller?: boolean;
|
|
257
|
-
whatsappConfig?: {
|
|
258
|
-
/** Seller's WhatsApp Business phone number, digits-only with country code e.g. "919876543210" */
|
|
259
|
-
phoneNumber?: string;
|
|
260
|
-
/** Meta WABA ID for this store */
|
|
261
|
-
wabaId?: string;
|
|
262
|
-
/** Meta Commerce Catalog ID linked to this store */
|
|
263
|
-
catalogId?: string;
|
|
264
|
-
/** Encrypted access token (AES-256-GCM via encryptPii) — never returned to client */
|
|
265
|
-
accessToken?: string;
|
|
266
|
-
/** Whether catalog sync is enabled for this store */
|
|
267
|
-
catalogSyncEnabled: boolean;
|
|
268
|
-
/** Timestamp of last successful catalog sync */
|
|
269
|
-
lastCatalogSyncAt?: Date;
|
|
270
|
-
/** Number of products synced in last run */
|
|
271
|
-
lastSyncCount?: number;
|
|
272
|
-
/** Status of last sync attempt */
|
|
273
|
-
lastSyncStatus?: "success" | "partial" | "failed";
|
|
274
|
-
/** True when wabaId + catalogId + accessToken are all set */
|
|
275
|
-
connected: boolean;
|
|
276
|
-
/** When the seller first connected their account */
|
|
277
|
-
connectedAt?: Date;
|
|
278
|
-
};
|
|
279
257
|
/**
|
|
280
258
|
* Who changed what, when, and why. See § "Status History" in CLAUDE.md.
|
|
281
259
|
*
|
|
@@ -300,9 +278,12 @@ export interface StoreDocument extends BaseDocument {
|
|
|
300
278
|
*/
|
|
301
279
|
export declare const STORE_TRACKED_FIELDS: readonly ["status", "isPublic", "isVerified", "isFeatured", "suspensionReason", "capabilities"];
|
|
302
280
|
/**
|
|
303
|
-
* PII on this document, for `withHistory`
|
|
304
|
-
*
|
|
305
|
-
*
|
|
281
|
+
* PII on this document, for the `withHistory` scrub.
|
|
282
|
+
*
|
|
283
|
+
* `accessToken` stays listed although the WhatsApp integration that produced
|
|
284
|
+
* one was removed 2026-10-20: a scrub list is cheap, and a future secret
|
|
285
|
+
* reaching this document under that name should be scrubbed by default
|
|
286
|
+
* rather than by someone remembering to add it.
|
|
306
287
|
*/
|
|
307
288
|
export declare const STORE_HISTORY_PII_FIELDS: readonly ["accessToken", "payoutDetails", "upiVpa", "accountNumber"];
|
|
308
289
|
export type { StoreCapability } from "../../auth/permissions/constants";
|
|
@@ -33,9 +33,12 @@ export const STORE_TRACKED_FIELDS = [
|
|
|
33
33
|
"capabilities",
|
|
34
34
|
];
|
|
35
35
|
/**
|
|
36
|
-
* PII on this document, for `withHistory`
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* PII on this document, for the `withHistory` scrub.
|
|
37
|
+
*
|
|
38
|
+
* `accessToken` stays listed although the WhatsApp integration that produced
|
|
39
|
+
* one was removed 2026-10-20: a scrub list is cheap, and a future secret
|
|
40
|
+
* reaching this document under that name should be scrubbed by default
|
|
41
|
+
* rather than by someone remembering to add it.
|
|
39
42
|
*/
|
|
40
43
|
export const STORE_HISTORY_PII_FIELDS = [
|
|
41
44
|
"accessToken",
|
|
@@ -228,7 +228,7 @@ export declare const storeFirestoreSchema: z.ZodObject<{
|
|
|
228
228
|
totalReviews: number;
|
|
229
229
|
averageRating?: number | undefined;
|
|
230
230
|
}>>;
|
|
231
|
-
capabilities: z.ZodOptional<z.ZodArray<z.
|
|
231
|
+
capabilities: z.ZodOptional<z.ZodArray<z.ZodEnum<[string, ...string[]]>, "many">>;
|
|
232
232
|
customCommissionRate: z.ZodOptional<z.ZodNumber>;
|
|
233
233
|
googleReviews: z.ZodOptional<z.ZodObject<{
|
|
234
234
|
placeId: z.ZodString;
|
|
@@ -347,60 +347,6 @@ export declare const storeFirestoreSchema: z.ZodObject<{
|
|
|
347
347
|
defaultProviderId: string;
|
|
348
348
|
}>>;
|
|
349
349
|
emiEnabled: z.ZodOptional<z.ZodBoolean>;
|
|
350
|
-
whatsappConfig: z.ZodOptional<z.ZodObject<{
|
|
351
|
-
phoneNumber: z.ZodOptional<z.ZodString>;
|
|
352
|
-
wabaId: z.ZodOptional<z.ZodString>;
|
|
353
|
-
catalogId: z.ZodOptional<z.ZodString>;
|
|
354
|
-
accessToken: z.ZodOptional<z.ZodString>;
|
|
355
|
-
catalogSyncEnabled: z.ZodBoolean;
|
|
356
|
-
lastCatalogSyncAt: z.ZodOptional<z.ZodUnion<[z.ZodDate, z.ZodString, z.ZodObject<{
|
|
357
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
358
|
-
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
359
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
360
|
-
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
361
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
362
|
-
}, z.ZodTypeAny, "passthrough">>]>>;
|
|
363
|
-
lastSyncCount: z.ZodOptional<z.ZodNumber>;
|
|
364
|
-
lastSyncStatus: z.ZodOptional<z.ZodEnum<["success", "partial", "failed"]>>;
|
|
365
|
-
connected: z.ZodBoolean;
|
|
366
|
-
connectedAt: z.ZodOptional<z.ZodUnion<[z.ZodDate, z.ZodString, z.ZodObject<{
|
|
367
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
368
|
-
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
369
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
370
|
-
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
371
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
372
|
-
}, z.ZodTypeAny, "passthrough">>]>>;
|
|
373
|
-
}, "strip", z.ZodTypeAny, {
|
|
374
|
-
catalogSyncEnabled: boolean;
|
|
375
|
-
connected: boolean;
|
|
376
|
-
phoneNumber?: string | undefined;
|
|
377
|
-
accessToken?: string | undefined;
|
|
378
|
-
wabaId?: string | undefined;
|
|
379
|
-
catalogId?: string | undefined;
|
|
380
|
-
lastCatalogSyncAt?: string | Date | z.objectOutputType<{
|
|
381
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
382
|
-
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
383
|
-
lastSyncCount?: number | undefined;
|
|
384
|
-
lastSyncStatus?: "success" | "failed" | "partial" | undefined;
|
|
385
|
-
connectedAt?: string | Date | z.objectOutputType<{
|
|
386
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
387
|
-
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
388
|
-
}, {
|
|
389
|
-
catalogSyncEnabled: boolean;
|
|
390
|
-
connected: boolean;
|
|
391
|
-
phoneNumber?: string | undefined;
|
|
392
|
-
accessToken?: string | undefined;
|
|
393
|
-
wabaId?: string | undefined;
|
|
394
|
-
catalogId?: string | undefined;
|
|
395
|
-
lastCatalogSyncAt?: string | Date | z.objectInputType<{
|
|
396
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
397
|
-
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
398
|
-
lastSyncCount?: number | undefined;
|
|
399
|
-
lastSyncStatus?: "success" | "failed" | "partial" | undefined;
|
|
400
|
-
connectedAt?: string | Date | z.objectInputType<{
|
|
401
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
402
|
-
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
403
|
-
}>>;
|
|
404
350
|
}, "strip", z.ZodTypeAny, {
|
|
405
351
|
status: "pending" | "active" | "rejected" | "suspended";
|
|
406
352
|
id: string;
|
|
@@ -470,22 +416,6 @@ export declare const storeFirestoreSchema: z.ZodObject<{
|
|
|
470
416
|
maxReviews?: number | undefined;
|
|
471
417
|
minRating?: number | undefined;
|
|
472
418
|
} | undefined;
|
|
473
|
-
whatsappConfig?: {
|
|
474
|
-
catalogSyncEnabled: boolean;
|
|
475
|
-
connected: boolean;
|
|
476
|
-
phoneNumber?: string | undefined;
|
|
477
|
-
accessToken?: string | undefined;
|
|
478
|
-
wabaId?: string | undefined;
|
|
479
|
-
catalogId?: string | undefined;
|
|
480
|
-
lastCatalogSyncAt?: string | Date | z.objectOutputType<{
|
|
481
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
482
|
-
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
483
|
-
lastSyncCount?: number | undefined;
|
|
484
|
-
lastSyncStatus?: "success" | "failed" | "partial" | undefined;
|
|
485
|
-
connectedAt?: string | Date | z.objectOutputType<{
|
|
486
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
487
|
-
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
488
|
-
} | undefined;
|
|
489
419
|
}, {
|
|
490
420
|
status: "pending" | "active" | "rejected" | "suspended";
|
|
491
421
|
id: string;
|
|
@@ -555,22 +485,6 @@ export declare const storeFirestoreSchema: z.ZodObject<{
|
|
|
555
485
|
maxReviews?: number | undefined;
|
|
556
486
|
minRating?: number | undefined;
|
|
557
487
|
} | undefined;
|
|
558
|
-
whatsappConfig?: {
|
|
559
|
-
catalogSyncEnabled: boolean;
|
|
560
|
-
connected: boolean;
|
|
561
|
-
phoneNumber?: string | undefined;
|
|
562
|
-
accessToken?: string | undefined;
|
|
563
|
-
wabaId?: string | undefined;
|
|
564
|
-
catalogId?: string | undefined;
|
|
565
|
-
lastCatalogSyncAt?: string | Date | z.objectInputType<{
|
|
566
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
567
|
-
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
568
|
-
lastSyncCount?: number | undefined;
|
|
569
|
-
lastSyncStatus?: "success" | "failed" | "partial" | undefined;
|
|
570
|
-
connectedAt?: string | Date | z.objectInputType<{
|
|
571
|
-
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
572
|
-
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
573
|
-
} | undefined;
|
|
574
488
|
}>;
|
|
575
489
|
export type StoreFromSchema = z.infer<typeof storeFirestoreSchema>;
|
|
576
490
|
/** Zod schema for store status — use instead of inline `z.enum(["pending",...])`. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from "./firestore.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { StoreStatusValues } from "./firestore.js";
|
|
4
|
+
import { ALL_STORE_CAPABILITIES } from "../../auth/permissions/constants.js";
|
|
4
5
|
import { auditTimestampsShape, firestoreDateSchema, rupeesSchema } from "../../../schemas/firestore-helpers.js";
|
|
5
6
|
// ─── Firestore document schema (W2) ───────────────────────────────────────────
|
|
6
7
|
// Mirrors StoreDocument in ./firestore.ts. Registered into SCHEMAS.firestore.stores.
|
|
@@ -70,7 +71,15 @@ export const storeFirestoreSchema = z.object({
|
|
|
70
71
|
averageRating: z.number().optional(),
|
|
71
72
|
})
|
|
72
73
|
.optional(),
|
|
73
|
-
|
|
74
|
+
/*
|
|
75
|
+
* 🛑 A `z.enum`, not `z.array(z.string())`. Nothing used to check a stored
|
|
76
|
+
* capability against the union, so a typo saved successfully and the gate it
|
|
77
|
+
* was meant to open never opened — with no error anywhere, because an
|
|
78
|
+
* unrecognised capability is indistinguishable from an ungranted one.
|
|
79
|
+
*/
|
|
80
|
+
capabilities: z
|
|
81
|
+
.array(z.enum(ALL_STORE_CAPABILITIES))
|
|
82
|
+
.optional(),
|
|
74
83
|
customCommissionRate: z.number().min(0).max(100).optional(),
|
|
75
84
|
googleReviews: z
|
|
76
85
|
.object({
|
|
@@ -83,20 +92,6 @@ export const storeFirestoreSchema = z.object({
|
|
|
83
92
|
.optional(),
|
|
84
93
|
shippingConfig: storeShippingConfigSchema.optional(),
|
|
85
94
|
emiEnabled: z.boolean().optional(),
|
|
86
|
-
whatsappConfig: z
|
|
87
|
-
.object({
|
|
88
|
-
phoneNumber: z.string().optional(),
|
|
89
|
-
wabaId: z.string().optional(),
|
|
90
|
-
catalogId: z.string().optional(),
|
|
91
|
-
accessToken: z.string().optional(),
|
|
92
|
-
catalogSyncEnabled: z.boolean(),
|
|
93
|
-
lastCatalogSyncAt: firestoreDateSchema.optional(),
|
|
94
|
-
lastSyncCount: z.number().int().optional(),
|
|
95
|
-
lastSyncStatus: z.enum(["success", "partial", "failed"]).optional(),
|
|
96
|
-
connected: z.boolean(),
|
|
97
|
-
connectedAt: firestoreDateSchema.optional(),
|
|
98
|
-
})
|
|
99
|
-
.optional(),
|
|
100
95
|
...auditTimestampsShape,
|
|
101
96
|
});
|
|
102
97
|
/** Zod schema for store status — use instead of inline `z.enum(["pending",...])`. */
|
|
@@ -174,54 +174,6 @@ export const authored = {
|
|
|
174
174
|
expectedUiState: "With the toggle OFF, /checkout offers only whichever of manual UPI/cash and COD are separately enabled — no 'Pay Online (PhonePe)' button. With it back ON, the button reappears.",
|
|
175
175
|
endResult: "The toggle is restored to ON, matching the state before this case started.",
|
|
176
176
|
},
|
|
177
|
-
"checklist-admin-site-system-whatsapp-credentials-persist": {
|
|
178
|
-
roles: ["admin"],
|
|
179
|
-
startPage: "/admin/site",
|
|
180
|
-
steps: [
|
|
181
|
-
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
182
|
-
"Open /admin/site, switch to the Integrations tab, and WRITE DOWN every WhatsApp field and its current masked state before touching anything.",
|
|
183
|
-
"Type QA-WA-TOKEN-552310 into the access-token field and fill any account identifier fields.",
|
|
184
|
-
"Save and RELOAD, then read how each field displays.",
|
|
185
|
-
"Open /api/site-settings in a private window and search for QA-WA-TOKEN-552310.",
|
|
186
|
-
"Open a public store page's source and search for it too.",
|
|
187
|
-
"RESTORE every field to exactly what step 3 recorded — clearing is not restoring, and a real Meta token cleared here cannot be recovered from the seed. Save and reload to confirm.",
|
|
188
|
-
],
|
|
189
|
-
inputs: { token: "QA-WA-TOKEN-552310" },
|
|
190
|
-
expectedBehaviour: "The token is encrypted at rest and masked on read. It is also decrypted on every read of a store document, so any page handing a raw store document to a client component serialises it into public HTML — which is why both the settings response and a public store page are checked rather than the admin form alone.",
|
|
191
|
-
expectedUiState: "After the reload the token displays masked. Neither the public settings response nor a public store page's source contains it.",
|
|
192
|
-
expectedData: { tokenInPublicSurfaces: 0 },
|
|
193
|
-
endResult: "The fields are cleared by the final step.",
|
|
194
|
-
},
|
|
195
|
-
"checklist-admin-site-system-whatsapp-channel-toggle-persists": {
|
|
196
|
-
roles: ["admin"],
|
|
197
|
-
startPage: "/admin/site",
|
|
198
|
-
steps: [
|
|
199
|
-
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
200
|
-
"Open /admin/site, switch to the Notifications tab, and read every channel toggle and its state. Four are listed: in-app, email, WhatsApp and SMS.",
|
|
201
|
-
"Turn the WHATSAPP channel off and save. Pick that one specifically — SMS is seeded OFF (and has no sender at all), so toggling it off would be a no-op that proves nothing.",
|
|
202
|
-
"RELOAD and read every toggle.",
|
|
203
|
-
"Check only the one changed.",
|
|
204
|
-
"Turn it back on, save, and reload to confirm.",
|
|
205
|
-
],
|
|
206
|
-
expectedBehaviour: "Off is the direction that proves persistence when the default is on: a toggle that never saves reads back as its default and passes a test that only ever turns it on. Saving one toggle must not rewrite the rest.",
|
|
207
|
-
expectedUiState: "After the reload the toggled channel is off and every other is unchanged. A toggle that has reverted to on is the failure, and the save reported success.",
|
|
208
|
-
endResult: "The toggle is restored.",
|
|
209
|
-
},
|
|
210
|
-
"checklist-admin-site-system-whatsapp-order-announcement-fires": {
|
|
211
|
-
roles: ["admin", "buyer"],
|
|
212
|
-
startPage: "/admin/site",
|
|
213
|
-
steps: [
|
|
214
|
-
"Sign in as admin@letitrip.in / TempPass123! and confirm the WhatsApp order channel is enabled.",
|
|
215
|
-
"Read whether real credentials are configured or whether the fields are empty.",
|
|
216
|
-
"Sign in as rehan.sheikh@gmail.com / TempPass123! and place an order that would trigger an order announcement.",
|
|
217
|
-
"Read whether the buyer opted into WhatsApp updates and what fee was charged for it.",
|
|
218
|
-
"Check the in-app notification for the order arrived.",
|
|
219
|
-
"If real credentials are configured, check whether a WhatsApp message arrived.",
|
|
220
|
-
],
|
|
221
|
-
expectedBehaviour: "WhatsApp order announcements are a paid per-store add-on, so the charge and the delivery must agree — a buyer charged the add-on fee and sent nothing is the failure that matters. With no credentials configured, the dispatch skips cleanly rather than failing loudly: the Meta secrets are seeded as empty strings rather than placeholders for exactly that reason.",
|
|
222
|
-
expectedUiState: "The in-app notification arrives regardless. With credentials configured a message arrives; without them nothing is sent and no error surfaces to the buyer. A charged add-on with no delivery is the finding.",
|
|
223
|
-
endResult: "One order exists. Record whether credentials were configured — the case reads differently either way.",
|
|
224
|
-
},
|
|
225
177
|
"checklist-admin-site-system-auction-bid-tiers-admin": {
|
|
226
178
|
roles: ["admin", "buyer"],
|
|
227
179
|
startPage: "/admin/site",
|
|
@@ -226,46 +226,6 @@ export const authored = {
|
|
|
226
226
|
expectedData: { otpRequiredAbove: true, otpRequiredBelow: false },
|
|
227
227
|
endResult: "Entering the correct code completes the order. Three items only add to ₹4,597 — the fourth is what actually crosses the threshold, and an earlier draft of this case stopped at three and could never have triggered the prompt it was checking for.",
|
|
228
228
|
},
|
|
229
|
-
"checklist-buying-buying-checkout-checkout-otp-whatsapp-hidden-without-phone": {
|
|
230
|
-
roles: ["buyer"],
|
|
231
|
-
startPage: "/checkout",
|
|
232
|
-
steps: [
|
|
233
|
-
"Sign in as admin@letitrip.in / TempPass123! and confirm Site Settings → Notifications → WhatsApp → 'WhatsApp OTP' is enabled.",
|
|
234
|
-
"Sign in as rehan.sheikh@gmail.com / TempPass123!.",
|
|
235
|
-
"Open /user/addresses and add an address named 'QA Address otp-whatsapp-hidden', 2 Test Road, Mumbai, Maharashtra 400001, leaving the phone field empty.",
|
|
236
|
-
"Add product-beyblade-original-dranzer-s (₹1,499), product-beyblade-original-driger-v (₹1,799), product-beyblade-metal-storm-pegasus (₹1,299) and product-beyblade-burst-regalia-genesis (₹1,399) to the cart, making ₹5,996.",
|
|
237
|
-
"Open /checkout, select 'QA Address otp-whatsapp-hidden' on Step 1, and continue to the payment step.",
|
|
238
|
-
"Select a non-COD payment method.",
|
|
239
|
-
"Read every option offered on the OTP prompt.",
|
|
240
|
-
],
|
|
241
|
-
inputs: { addressLabel: "QA Address otp-whatsapp-hidden", phone: "", subtotal: 5996 },
|
|
242
|
-
expectedBehaviour: "The WhatsApp channel needs three things at once — admin-enabled, real credentials, and a phone number on the SELECTED address. Missing the third hides the option rather than offering it and failing at send time, which would waste the buyer's OTP window on a channel that could never deliver.",
|
|
243
|
-
expectedUiState: "The prompt offers email only. There is no 'Send via WhatsApp instead' control, disabled or otherwise, even though the same setting shows one for an address that has a phone.",
|
|
244
|
-
expectedData: { whatsappOptionPresent: false },
|
|
245
|
-
endResult: "The order still completes by email OTP. Delete the address afterwards so it does not accumulate across runs.",
|
|
246
|
-
},
|
|
247
|
-
"checklist-buying-buying-checkout-checkout-otp-whatsapp-option": {
|
|
248
|
-
roles: ["buyer"],
|
|
249
|
-
startPage: "/checkout",
|
|
250
|
-
steps: [
|
|
251
|
-
"Sign in as admin@letitrip.in / TempPass123! and confirm Site Settings → Notifications → WhatsApp → 'WhatsApp OTP' is enabled with real Meta Cloud API credentials.",
|
|
252
|
-
"Sign in as rehan.sheikh@gmail.com / TempPass123!.",
|
|
253
|
-
"Open /user/addresses and add a phone number to the existing address 'Home — 123 Stadium Lane, Vijay Nagar, Indore, Madhya Pradesh 452010' if it does not already have one.",
|
|
254
|
-
"Add product-beyblade-original-dranzer-s (₹1,499), product-beyblade-original-driger-v (₹1,799), product-beyblade-metal-storm-pegasus (₹1,299) and product-beyblade-burst-regalia-genesis (₹1,399) to the cart, making ₹5,996.",
|
|
255
|
-
"Open /cart and click 'Proceed to checkout'.",
|
|
256
|
-
"Select the address with a phone number on Step 1 and click 'Continue'.",
|
|
257
|
-
"Click 'Continue to payment' on Step 2.",
|
|
258
|
-
"On Step 3, select a non-COD payment method.",
|
|
259
|
-
"Read the default send channel shown on the OTP prompt.",
|
|
260
|
-
"Click 'Send via WhatsApp instead'.",
|
|
261
|
-
"Type the code received on WhatsApp into the OTP field and submit it.",
|
|
262
|
-
],
|
|
263
|
-
inputs: { subtotal: 5996, defaultChannel: "email", alternateChannel: "WhatsApp" },
|
|
264
|
-
expectedBehaviour: "Email is the default channel and WhatsApp is opt-in per attempt. The alternate appears only when the feature is enabled, real Meta credentials are configured, and the selected address carries a phone — the seeded Meta secrets are empty strings rather than placeholders precisely so a missing credential skips cleanly instead of making a billed call that fails.",
|
|
265
|
-
expectedUiState: "The prompt first shows a masked email. After 'Send via WhatsApp instead' it shows a masked phone in the shape '+91 ••••••7890'. The code that arrives on WhatsApp is accepted and payment proceeds.",
|
|
266
|
-
expectedData: { defaultChannel: "email" },
|
|
267
|
-
endResult: "The order is placed after the WhatsApp code verifies. With no real Meta credentials configured this case is unreachable — answer null rather than reporting the missing option as a bug.",
|
|
268
|
-
},
|
|
269
229
|
"checklist-buying-buying-checkout-checkout-phonepe-charge-includes-shipping": {
|
|
270
230
|
roles: ["buyer"],
|
|
271
231
|
startPage: "/checkout",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* WHY: Authored six-part procedures for content-discovery/authenticity-checker.
|
|
3
|
-
* WHAT:
|
|
3
|
+
* WHAT: 22 cases, keyed by full checklist id.
|
|
4
4
|
*
|
|
5
5
|
* 🛑 EVERY CASE IS WRITTEN AS BEFORE → AFTER, because this feature's whole
|
|
6
6
|
* failure mode is a confident, plausible, wrong answer returned with HTTP 200. A
|
|
@@ -44,7 +44,7 @@ export const authored = {
|
|
|
44
44
|
startPage: "/tools/authenticity",
|
|
45
45
|
steps: [
|
|
46
46
|
"Open /tools/authenticity signed out.",
|
|
47
|
-
"Confirm the LOOKUP FORM itself is there and usable —
|
|
47
|
+
"Confirm the LOOKUP FORM itself is there and usable — 'Which bey is it?', 'Code on the box', a collapsed 'More details' holding the name-as-printed, brand, generation and how-it-was-sold fields, and a 'Check it' button.",
|
|
48
48
|
"Confirm there is no sign-in card and no 'Sign in to run a lookup' text anywhere on the page.",
|
|
49
49
|
"Enter A0813 as the code and submit, still signed out.",
|
|
50
50
|
"Confirm a real assessment comes back rather than an error or a prompt to sign in.",
|
|
@@ -475,4 +475,116 @@ export const authoredTypeahead = {
|
|
|
475
475
|
expectedUiState: "The result renders immediately. The network log shows no fetch to the search artifact or any /api/search* endpoint.",
|
|
476
476
|
endResult: "Read-only; nothing persists.",
|
|
477
477
|
},
|
|
478
|
+
/* ── The model picker and the per-model code list (2026-10-20) ──────────
|
|
479
|
+
* 🛑 The reported bug these exist for: typing "l drago" returned
|
|
480
|
+
* "Inconclusive — Nothing contradicts it, and nothing confirms it either",
|
|
481
|
+
* while the tool held 33 recorded box codes for Lightning L-Drago, 35 for
|
|
482
|
+
* Meteo and 27 for Destructor and had no way to reach any of them. Every
|
|
483
|
+
* table was keyed by CODE, so naming a bey could never surface them.
|
|
484
|
+
*
|
|
485
|
+
* So each case compares the answer against data the tool DEMONSTRABLY HAS.
|
|
486
|
+
* "Check the picker works" passes against the bug; "picking Lightning
|
|
487
|
+
* L-Drago must list its 33 codes" does not.
|
|
488
|
+
*/
|
|
489
|
+
"checklist-content-discovery-authenticity-checker-model-picker-finds-l-drago": {
|
|
490
|
+
roles: ["guest"],
|
|
491
|
+
startPage: "/tools/authenticity",
|
|
492
|
+
steps: [
|
|
493
|
+
"Open /tools/authenticity.",
|
|
494
|
+
"Confirm the FIRST field is 'Which bey is it?' and is a searchable select, not a plain text box.",
|
|
495
|
+
"Open it and type: l drago",
|
|
496
|
+
"Confirm all three L-Drago releases are offered — Lightning L-Drago 100HF, Meteo L-Drago LW105LF and L-Drago Destructor F:S.",
|
|
497
|
+
"Confirm each offered row states how many box codes are on file for it.",
|
|
498
|
+
"Clear the search and type: pegasis",
|
|
499
|
+
"Confirm Storm Pegasus still appears, even though the list spells it Pegasus.",
|
|
500
|
+
"Answer no if 'l drago' offers nothing, or if the field is a free-text input with no list.",
|
|
501
|
+
],
|
|
502
|
+
inputs: { search: "l drago" },
|
|
503
|
+
expectedBehaviour: "BEFORE: the first field was a free-text 'Model name'. Typing 'l drago' matched four releases, so the engine refused to pick one and returned an inconclusive verdict — correct, and useless, because the three L-Dragos it declined to choose between have 95 recorded box codes between them and the screen never said so. AFTER: the picker resolves exactly one bey, which is what unlocks the per-model code list. It searches aliases as well as labels, because Takara Tomy romanises the line Pegasis and Hasbro prints Pegasus — a label-only filter would find neither from the other.",
|
|
504
|
+
expectedUiState: "A searchable select labelled 'Which bey is it?' listing three L-Drago rows, each annotated with a box-code count. Beys with codes on file are offered before beys without.",
|
|
505
|
+
endResult: "Nothing is written. The picker only reads a bundled list.",
|
|
506
|
+
},
|
|
507
|
+
"checklist-content-discovery-authenticity-checker-picked-model-lists-its-box-codes": {
|
|
508
|
+
roles: ["guest"],
|
|
509
|
+
startPage: "/tools/authenticity",
|
|
510
|
+
steps: [
|
|
511
|
+
"Open /tools/authenticity.",
|
|
512
|
+
"In 'Which bey is it?', search for and pick: Lightning L-Drago 100HF",
|
|
513
|
+
"Leave 'Code on the box' EMPTY.",
|
|
514
|
+
"Press 'Check it'.",
|
|
515
|
+
"Read the verdict line, then look for a panel headed 'Box codes recorded for Lightning L-Drago 100HF'.",
|
|
516
|
+
"Count the codes it lists.",
|
|
517
|
+
"Answer no if the verdict is 'Inconclusive — Nothing contradicts it, and nothing confirms it either', or if no code list appears.",
|
|
518
|
+
],
|
|
519
|
+
inputs: { modelSlug: "lightning-l-drago-100hf" },
|
|
520
|
+
expectedBehaviour: "BEFORE: naming this bey with no code produced 'Inconclusive — Nothing contradicts it, and nothing confirms it either' and a physical checklist. True, in that nothing had been checked — and it withheld the 33 box codes the tables record for this exact bey, which is the single most useful thing the tool holds and the one thing the user had asked for. AFTER: the verdict is 'I know this one. Now find the code stamped on the box.' — still not a judgement, because nothing has been checked, but with the next step named and the 33 codes listed to check against.",
|
|
521
|
+
expectedUiState: "Verdict badge 'Need a bit more', headline 'I know this one. Now find the code stamped on the box.', a caveat naming the count, and a panel listing 33 codes as badges. A link reading 'Everything we hold on Lightning L-Drago 100HF' points at the model's own category page.",
|
|
522
|
+
expectedData: { recordedCodes: 33 },
|
|
523
|
+
endResult: "Read-only.",
|
|
524
|
+
},
|
|
525
|
+
"checklist-content-discovery-authenticity-checker-picked-model-plus-its-own-code": {
|
|
526
|
+
roles: ["guest"],
|
|
527
|
+
startPage: "/tools/authenticity",
|
|
528
|
+
steps: [
|
|
529
|
+
"Pick 'Lightning L-Drago 100HF' in 'Which bey is it?'.",
|
|
530
|
+
"Enter A0910 in 'Code on the box' — a code recorded against this exact bey.",
|
|
531
|
+
"Press 'Check it' and read the verdict.",
|
|
532
|
+
"Expand 'How I got there' and find the row about the code.",
|
|
533
|
+
"Press 'Start over'. Pick Lightning L-Drago 100HF again, this time enter A0310 — a real code recorded against a DIFFERENT bey.",
|
|
534
|
+
"Read the verdict and expand the working-out again.",
|
|
535
|
+
"Answer no if the second case reads as a mismatch, a discrepancy, or anything implying the item is wrong.",
|
|
536
|
+
],
|
|
537
|
+
inputs: { modelSlug: "lightning-l-drago-100hf", recordedCode: "A0910", otherBeyCode: "A0310" },
|
|
538
|
+
expectedBehaviour: "A0910 is in this bey's own list, so the check reads as agreement — the strongest thing the tool can say from data, and it still says so is not proof. A0310 is recorded, but on Earth Aquila: that is WEAK SUPPORT, not a mismatch, because a production date covers whatever was boxed that day. The distinction is the whole point. Reporting 'that code belongs to a different bey' as a discrepancy would manufacture suspicion out of how the tables are organised, and the panel highlights the code you entered inside the list so you can see where it sits.",
|
|
539
|
+
expectedUiState: "First run: 'Consistent with an original', and a row reading that the code is recorded on genuine boxes of this exact bey. Second run: still not adverse — a neutral row saying the code is recorded but not against this bey, with the phrase 'weak support rather than a mismatch'.",
|
|
540
|
+
endResult: "Read-only.",
|
|
541
|
+
},
|
|
542
|
+
"checklist-content-discovery-authenticity-checker-missing-code-is-not-an-accusation": {
|
|
543
|
+
roles: ["guest"],
|
|
544
|
+
startPage: "/tools/authenticity",
|
|
545
|
+
steps: [
|
|
546
|
+
"Pick 'Lightning L-Drago 100HF' in 'Which bey is it?'.",
|
|
547
|
+
"Enter Z9999 in 'Code on the box' — well-formed, and in none of the tables.",
|
|
548
|
+
"Press 'Check it'.",
|
|
549
|
+
"Read the verdict, the code panel and the working-out.",
|
|
550
|
+
"Answer no if any sentence implies the item is fake, counterfeit or a reproduction, or if the verdict is more severe than 'Inconclusive'.",
|
|
551
|
+
],
|
|
552
|
+
inputs: { modelSlug: "lightning-l-drago-100hf", code: "Z9999" },
|
|
553
|
+
expectedBehaviour: "A code absent from a model's list means UNRECORDED, never wrong. These tables are what collectors photographed, not a manufacturing record: 38 of 221 canonical beys have any recorded code at all, new genuine codes turn up regularly, and counterfeiters print real codes anyway. The panel must say so where a user will actually read it, not only inside the collapsed working-out — the reading 'my code is not in the list, so it is fake' is the one this whole feature has to defend against.",
|
|
554
|
+
expectedUiState: "Verdict 'Inconclusive'. A neutral row reading 'Not among the 33 codes recorded for Lightning L-Drago 100HF' whose text says 'unrecorded, not wrong'. The code panel carries a line beginning 'A code missing from this list means unrecorded, not fake.'",
|
|
555
|
+
endResult: "Read-only.",
|
|
556
|
+
},
|
|
557
|
+
"checklist-content-discovery-authenticity-checker-working-out-is-collapsed-by-default": {
|
|
558
|
+
roles: ["guest"],
|
|
559
|
+
startPage: "/tools/authenticity",
|
|
560
|
+
steps: [
|
|
561
|
+
"Pick 'Lightning L-Drago 100HF' and enter A0910. Press 'Check it'.",
|
|
562
|
+
"WITHOUT expanding anything, confirm you can read the verdict badge, the headline, the caveat and the recorded-code list.",
|
|
563
|
+
"Confirm the reasoning is behind a single collapsed control reading 'How I got there — N checks'.",
|
|
564
|
+
"Expand it and confirm every individual check is still there, each with its own confidence chip.",
|
|
565
|
+
"Press 'Start over'. Now enter the code A0813 with no model picked — a code the sources record as a midfake batch.",
|
|
566
|
+
"Confirm the working-out is ALREADY OPEN this time, without being clicked.",
|
|
567
|
+
"Answer no if the reasoning is expanded by default on the clean run, or collapsed on the midfake run.",
|
|
568
|
+
],
|
|
569
|
+
inputs: { modelSlug: "lightning-l-drago-100hf", cleanCode: "A0910", midfakeCode: "A0813" },
|
|
570
|
+
expectedBehaviour: "BEFORE: every check rendered expanded under a 'What I checked' heading — up to eleven rows of reasoning between the buyer and the answer they asked for. AFTER: it is collapsed, not deleted, because 'why should I believe this' has to stay one tap away for a tool whose entire posture is that it hedges and cites. A CONCERN forces it open: the one case where the reasoning IS the answer is the case where something is wrong, and the user who never expands it must not be the user who never finds out.",
|
|
571
|
+
expectedUiState: "Clean run: verdict block, code panel, a collapsed 'How I got there — N checks', then the physical checks. Midfake run: the same control, already open.",
|
|
572
|
+
endResult: "Read-only.",
|
|
573
|
+
},
|
|
574
|
+
"checklist-content-discovery-authenticity-checker-result-scrolls-into-view": {
|
|
575
|
+
roles: ["guest"],
|
|
576
|
+
startPage: "/tools/authenticity",
|
|
577
|
+
steps: [
|
|
578
|
+
"Resize the browser to a phone viewport (about 390 x 740) or use device emulation.",
|
|
579
|
+
"Pick 'Lightning L-Drago 100HF' and enter A0910.",
|
|
580
|
+
"Scroll so the 'Check it' button is visible, and note what is on screen.",
|
|
581
|
+
"Press 'Check it'.",
|
|
582
|
+
"Without scrolling yourself, confirm the verdict badge and headline are now on screen.",
|
|
583
|
+
"Answer no if the page does not move and the verdict is below the fold.",
|
|
584
|
+
],
|
|
585
|
+
inputs: { viewport: "390x740", modelSlug: "lightning-l-drago-100hf", code: "A0910" },
|
|
586
|
+
expectedBehaviour: "BEFORE: the form is taller than a phone viewport, so the answer rendered below the fold and pressing 'Check it' looked like it had done nothing — at the one moment this tool must not be ambiguous. AFTER: the result is scrolled into view on every fresh assessment, including the re-run a clarifying question triggers, and anchored at the top of the viewport rather than the middle so the badge and headline land where the eye already is.",
|
|
587
|
+
expectedUiState: "After submitting, the verdict badge and headline are visible without manual scrolling.",
|
|
588
|
+
endResult: "Read-only.",
|
|
589
|
+
},
|
|
478
590
|
};
|
|
@@ -81,22 +81,6 @@ export const authored = {
|
|
|
81
81
|
expectedData: { published: true },
|
|
82
82
|
endResult: "The listing survives a reload of the public page and appears in /store/products. Delete it afterwards.",
|
|
83
83
|
},
|
|
84
|
-
"checklist-selling-quick-add-minimum-details-whatsapp-shows-the-same-fields": {
|
|
85
|
-
roles: ["seller"],
|
|
86
|
-
startPage: "/store/whatsapp",
|
|
87
|
-
steps: [
|
|
88
|
-
SIGN_IN_SELLER,
|
|
89
|
-
"Publish 'Minimum Details Probe' from /store/products/new as in the previous case, with Price 499.",
|
|
90
|
-
"Open /store/whatsapp and find the catalog preview.",
|
|
91
|
-
"Locate the tile for 'Minimum Details Probe'.",
|
|
92
|
-
"Read every piece of information the tile shows.",
|
|
93
|
-
"Compare that list against the fields the quick form asked for.",
|
|
94
|
-
],
|
|
95
|
-
inputs: { title: "Minimum Details Probe", price: 499 },
|
|
96
|
-
expectedBehaviour: "What WhatsApp shows is a subset of what the short form collects — title, price, image, condition and stock. This is the reason the short form is the right shape: a seller who fills only it has already supplied everything a WhatsApp buyer will see, so nothing is missing from the channel most of them arrive through.",
|
|
97
|
-
expectedUiState: "The tile shows the image, the name and ₹499. Nothing on it is blank or a placeholder, and nothing it shows was absent from the quick form.",
|
|
98
|
-
endResult: "Read-only against the catalog preview. Delete the probe listing afterwards.",
|
|
99
|
-
},
|
|
100
84
|
"checklist-selling-quick-add-minimum-details-advanced-flip-keeps-values": {
|
|
101
85
|
roles: ["seller"],
|
|
102
86
|
startPage: "/store/products/new",
|
|
@@ -23,7 +23,7 @@ export const authored = {
|
|
|
23
23
|
"Click 'All Guides' to reach /store/guide. It is a hub and it links the same six sub-guides, so each one has two routes in — check both agree.",
|
|
24
24
|
"Open each of the six in turn and read its content: /store/guide/listings, /store/guide/orders, /store/guide/finance, /store/guide/settings, /store/guide/capabilities, /store/guide/whatsapp.",
|
|
25
25
|
"Write down any that renders empty, 404s, or repeats another page's text.",
|
|
26
|
-
"Check each guide against the feature it describes — open that feature and confirm the guide's instructions match what is on screen.
|
|
26
|
+
"Check each guide against the feature it describes — open that feature and confirm the guide's instructions match what is on screen.",
|
|
27
27
|
"Follow every link inside the guides and note where each lands.",
|
|
28
28
|
],
|
|
29
29
|
expectedBehaviour: "Every seller guide renders its own content and every link in it resolves. A guide describing a screen that has since changed is worse than no guide, because the seller trusts it and then cannot find what it names. The sidebar group defaulting closed is deliberate — guides are reference, not daily work — so a tester who does not expand it will wrongly conclude they are missing.",
|
|
@@ -67,85 +67,6 @@ export const authored = {
|
|
|
67
67
|
expectedUiState: "The message names the missing configuration in plain English. It does not surface a provider error code, an API key, or a raw response body. The public store page shows no empty Google reviews section.",
|
|
68
68
|
endResult: "Nothing is synced. If credentials ARE configured on this environment, record that and read what the sync actually imported instead.",
|
|
69
69
|
},
|
|
70
|
-
"checklist-selling-seller-marketing-extras-seller-whatsapp-catalog": {
|
|
71
|
-
roles: ["seller"],
|
|
72
|
-
startPage: "/store/whatsapp",
|
|
73
|
-
steps: [
|
|
74
|
-
"Sign in as tyson@beybladearena.in / TempPass123!.",
|
|
75
|
-
"Open /store/whatsapp and read every control.",
|
|
76
|
-
"Read what it says about the connection state.",
|
|
77
|
-
"Read whether it names the business account and catalog it would sync with.",
|
|
78
|
-
"Trigger a catalog action without a token configured and read the message.",
|
|
79
|
-
],
|
|
80
|
-
expectedBehaviour: "The catalog surface reports its connection state honestly and declines cleanly when unconfigured. It is the reader of the store's WhatsApp configuration, which is stored encrypted and decrypted on every store read — so what this page shows is the one place the configuration is legitimately visible to its owner.",
|
|
81
|
-
expectedUiState: "The connection state is stated rather than implied. An unconfigured action produces a readable message naming what is missing, not a provider error. The business account and catalog identifiers are shown to the owner but partially masked.",
|
|
82
|
-
endResult: "Nothing is synced.",
|
|
83
|
-
},
|
|
84
|
-
"checklist-selling-seller-marketing-extras-seller-whatsapp-token-save": {
|
|
85
|
-
roles: ["seller", "guest"],
|
|
86
|
-
startPage: "/store/whatsapp",
|
|
87
|
-
steps: [
|
|
88
|
-
"Sign in as tyson@beybladearena.in / TempPass123!.",
|
|
89
|
-
"Open /store/whatsapp and type QA-WHATSAPP-TOKEN-118427 into the access-token field.",
|
|
90
|
-
"Save and RELOAD, then read how the token is displayed — a set token renders as a mask (••••••), never as the value typed.",
|
|
91
|
-
"Open the browser's View Source on that settings page and search for QA-WHATSAPP-TOKEN-118427.",
|
|
92
|
-
"Open /stores/store-beyblade-arena in a private window with no session.",
|
|
93
|
-
"Open View Source there and search for QA-WHATSAPP-TOKEN-118427 and for accessToken.",
|
|
94
|
-
"Clear the token field, save, and reload to confirm it is gone. Clearing is the correct ending here, unusually: no seeded store carries a whatsappConfig, so there is no prior value to restore and the field started empty.",
|
|
95
|
-
],
|
|
96
|
-
inputs: { token: "QA-WHATSAPP-TOKEN-118427" },
|
|
97
|
-
expectedBehaviour: "The token is stored double-encrypted and shown masked to its owner. Because it is decrypted on every read of the store document, the real risk is a page that passes that document to a client component — which serialises it into the public page HTML. The PUBLIC page source is therefore the assertion, not the masked field.",
|
|
98
|
-
expectedUiState: "After the reload the owner sees a masked value rather than the full token. The public store page's source contains neither the token nor the word accessToken anywhere, including inside the embedded data payload.",
|
|
99
|
-
expectedData: { tokenInPublicSource: 0 },
|
|
100
|
-
endResult: "The token is cleared by the final step. A hit on the public page is a credential leak and fails the case outright, however the settings page renders.",
|
|
101
|
-
},
|
|
102
|
-
"checklist-selling-seller-marketing-extras-seller-whatsapp-import-runs-in-background": {
|
|
103
|
-
roles: ["seller"],
|
|
104
|
-
startPage: "/store/whatsapp",
|
|
105
|
-
steps: [
|
|
106
|
-
"Sign in as tyson@beybladearena.in / TempPass123!.",
|
|
107
|
-
"Open /store/whatsapp and start an import.",
|
|
108
|
-
"Read what the page shows immediately — whether it blocks or returns.",
|
|
109
|
-
"Navigate to another store page and back.",
|
|
110
|
-
"Read whether the import's progress is still reported.",
|
|
111
|
-
"Wait for it to finish and read the summary.",
|
|
112
|
-
],
|
|
113
|
-
expectedBehaviour: "An import of unknown size is enqueued as a job rather than run inside the request — a route that fans out over a whole catalogue is exactly the shape the ten-second function ceiling kills in production while local runs pass. The page subscribes to the job's progress instead of waiting on a response.",
|
|
114
|
-
expectedUiState: "The page returns immediately with a job accepted rather than freezing. Progress survives navigating away and back. A completion summary states what was imported. A request that hangs and then times out is the failure this case exists for.",
|
|
115
|
-
endResult: "Whatever was imported persists. With no credentials configured the import will decline instead — record that rather than failing the case.",
|
|
116
|
-
},
|
|
117
|
-
"checklist-selling-seller-marketing-extras-seller-whatsapp-import-skips-already-synced": {
|
|
118
|
-
roles: ["seller"],
|
|
119
|
-
startPage: "/store/whatsapp",
|
|
120
|
-
steps: [
|
|
121
|
-
"Sign in as tyson@beybladearena.in / TempPass123!.",
|
|
122
|
-
"Open /store/whatsapp and run an import, noting the summary and the store's product count.",
|
|
123
|
-
"Run the SAME import a second time without changing anything.",
|
|
124
|
-
"Read the second summary and compare it against the first.",
|
|
125
|
-
"Open /store/products and read the product count again.",
|
|
126
|
-
"Search the products list for any duplicated title.",
|
|
127
|
-
],
|
|
128
|
-
expectedBehaviour: "A second import skips what is already synced rather than creating duplicates. This is the same idempotency the seed data needs: an import keyed on a stable external identifier upserts, while one keyed on anything regenerated per run creates a fresh copy every time and reports success.",
|
|
129
|
-
expectedUiState: "The second summary reports items skipped rather than a second full import. The product count is unchanged and no title appears twice.",
|
|
130
|
-
expectedData: { duplicateTitles: 0 },
|
|
131
|
-
endResult: "No duplicates exist. A doubled product count after a repeated import is the failure, and the summary will still have read as successful. NOTE: no seeded store carries a whatsappConfig at all, so with no Meta credentials configured BOTH imports will decline and there is nothing to compare — record that and answer null rather than reading two declines as a pass. Two identical declines are not evidence that duplicates are skipped.",
|
|
132
|
-
},
|
|
133
|
-
"checklist-selling-seller-marketing-extras-seller-whatsapp-push-product-link-opens": {
|
|
134
|
-
roles: ["seller"],
|
|
135
|
-
startPage: "/store/products",
|
|
136
|
-
steps: [
|
|
137
|
-
"Sign in as tyson@beybladearena.in / TempPass123!.",
|
|
138
|
-
"Open /store/products and use the WhatsApp push or share control on 'Beyblade Burst B-01 Valkyrie'.",
|
|
139
|
-
"Read the message it composes before sending anything.",
|
|
140
|
-
"Read the product link inside it and note its host and path.",
|
|
141
|
-
"Open that link in a private window with no session.",
|
|
142
|
-
"Read the page it opens.",
|
|
143
|
-
],
|
|
144
|
-
inputs: { productId: "product-beyblade-burst-valkyrie" },
|
|
145
|
-
expectedBehaviour: "The shared link is a public, canonical URL a stranger can open. There is one definition of the site host and everything derives from it — two owners drifted once and every sitemap URL pointed at a host that redirected, which is what took the site out of search.",
|
|
146
|
-
expectedUiState: "The message contains a link on the canonical host with an unprefixed path. Opening it signed out renders the product page directly rather than redirecting, and does not 404.",
|
|
147
|
-
endResult: "Nothing is sent. A link that redirects before landing is worth recording — every redirect is a hop a shared link pays on every open.",
|
|
148
|
-
},
|
|
149
70
|
"checklist-selling-seller-marketing-extras-seller-reviews-response": {
|
|
150
71
|
roles: ["seller", "guest"],
|
|
151
72
|
startPage: "/store/reviews",
|
|
@@ -141,7 +141,7 @@ export const authored = {
|
|
|
141
141
|
* Measured 2026-09-29: SELLER_ROW_ACTIONS.orders is
|
|
142
142
|
* [VIEW, EDIT, TRACK, RESEND] — no share. SellerOrdersView mentions
|
|
143
143
|
* WhatsApp only as the buyer's purchased add-on flag
|
|
144
|
-
*
|
|
144
|
+
* only as `wa.me` links, and every one of those in
|
|
145
145
|
* the codebase is on the contact page, the chat button or the buyer's own
|
|
146
146
|
* payment page. The registry's WhatsApp actions are store SETUP
|
|
147
147
|
* (whatsapp-connect, catalog-sync, catalog-import).
|