@wopr-network/platform-ui-core 1.27.8 → 1.27.9
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/next.config.ts +1 -2
- package/package.json +17 -17
- package/src/__tests__/account-switcher.test.tsx +21 -20
- package/src/__tests__/activity-page.test.tsx +2 -6
- package/src/__tests__/add-payment-method-dialog.test.tsx +9 -32
- package/src/__tests__/admin-api.test.ts +1 -6
- package/src/__tests__/admin-gpu-api.test.ts +1 -3
- package/src/__tests__/admin-marketplace-api.test.ts +1 -4
- package/src/__tests__/admin-middleware.test.ts +76 -83
- package/src/__tests__/affiliate-dashboard.test.tsx +3 -3
- package/src/__tests__/api-401-redirect.test.ts +46 -9
- package/src/__tests__/api-client.test.ts +3 -5
- package/src/__tests__/api-config.test.ts +22 -42
- package/src/__tests__/api-fleet-resources.test.ts +1 -2
- package/src/__tests__/api-fleet-trpc.test.ts +2 -8
- package/src/__tests__/api-null-guards.test.ts +3 -1
- package/src/__tests__/audit-log-table-pagination.test.tsx +2 -6
- package/src/__tests__/auth-password-reset.test.tsx +7 -21
- package/src/__tests__/auth-redirect.test.tsx +8 -2
- package/src/__tests__/auth.test.tsx +25 -23
- package/src/__tests__/auto-topup-card.test.tsx +4 -12
- package/src/__tests__/backups-tab.test.tsx +3 -4
- package/src/__tests__/billing-layout-nav-hidden.test.tsx +5 -37
- package/src/__tests__/billing-payment-org-invoices.test.tsx +2 -18
- package/src/__tests__/billing.test.tsx +8 -39
- package/src/__tests__/bot-settings/resources-tab.test.tsx +1 -3
- package/src/__tests__/bot-settings/storage-tab.test.tsx +1 -3
- package/src/__tests__/bot-settings/vps-upgrade-card.test.tsx +1 -3
- package/src/__tests__/bot-settings-restart.test.tsx +1 -3
- package/src/__tests__/bot-settings.test.tsx +2 -6
- package/src/__tests__/brand.test.ts +6 -26
- package/src/__tests__/buy-credits-panel.test.tsx +1 -3
- package/src/__tests__/buy-crypto-credits-panel.test.tsx +101 -119
- package/src/__tests__/capability-conflicts.test.ts +2 -8
- package/src/__tests__/capability-resolver.test.tsx +2 -12
- package/src/__tests__/channel-wizard.test.tsx +4 -17
- package/src/__tests__/chat/chat-panel.test.tsx +1 -4
- package/src/__tests__/chat-store.test.ts +5 -15
- package/src/__tests__/command-center.test.tsx +10 -12
- package/src/__tests__/compliance-retention-edit.test.tsx +3 -6
- package/src/__tests__/confirmation-tracker.test.tsx +3 -18
- package/src/__tests__/coupon-input.test.tsx +1 -3
- package/src/__tests__/create-instance.test.tsx +1 -3
- package/src/__tests__/credit-balance.test.tsx +4 -12
- package/src/__tests__/credits.test.tsx +32 -85
- package/src/__tests__/email-verification-banner.test.tsx +2 -6
- package/src/__tests__/error-boundaries.test.tsx +0 -1
- package/src/__tests__/fetch-pricing.test.ts +2 -1
- package/src/__tests__/field-oauth.test.tsx +2 -6
- package/src/__tests__/fixtures/mock-manifests-data.js +1 -3
- package/src/__tests__/fixtures/mock-manifests.ts +2 -4
- package/src/__tests__/fleet-health-timestamp.test.tsx +1 -8
- package/src/__tests__/fleet-health-update.test.tsx +1 -8
- package/src/__tests__/gpu-dashboard.test.tsx +2 -6
- package/src/__tests__/instance-detail.test.tsx +3 -9
- package/src/__tests__/instance-list.test.tsx +1 -5
- package/src/__tests__/layout-snapshots.test.tsx +64 -11
- package/src/__tests__/marketplace-admin.test.tsx +2 -6
- package/src/__tests__/marketplace.test.tsx +11 -35
- package/src/__tests__/merge-api-rates.test.ts +1 -6
- package/src/__tests__/middleware.test.ts +32 -219
- package/src/__tests__/next-config-headers.test.ts +1 -3
- package/src/__tests__/notifications.test.tsx +4 -11
- package/src/__tests__/oauth-buttons.test.tsx +36 -59
- package/src/__tests__/oauth-error-mapping.test.tsx +2 -6
- package/src/__tests__/observability.test.tsx +23 -36
- package/src/__tests__/onboarding-page.test.tsx +4 -6
- package/src/__tests__/org-billing-api.test.tsx +1 -6
- package/src/__tests__/plugin-install-flow.test.tsx +28 -58
- package/src/__tests__/plugin-registry.test.tsx +3 -11
- package/src/__tests__/plugin-tool-sync.test.ts +1 -3
- package/src/__tests__/plugins-catalog-error.test.tsx +2 -6
- package/src/__tests__/plugins-toggle-race.test.tsx +3 -5
- package/src/__tests__/portfolio-chart.test.tsx +2 -6
- package/src/__tests__/promotion-form.test.tsx +2 -6
- package/src/__tests__/promotions-list.test.tsx +1 -3
- package/src/__tests__/provider-key-api.test.ts +2 -1
- package/src/__tests__/resend-verification-button.test.tsx +8 -24
- package/src/__tests__/secrets-audit-pagination.test.tsx +1 -3
- package/src/__tests__/settings.test.tsx +11 -21
- package/src/__tests__/setup-checklist.test.tsx +3 -9
- package/src/__tests__/setup.ts +25 -6
- package/src/__tests__/snapshot-api.test.ts +2 -1
- package/src/__tests__/step-superpowers.test.tsx +1 -3
- package/src/__tests__/tenant-context.test.tsx +1 -6
- package/src/__tests__/tenant-keys-api.test.ts +3 -4
- package/src/__tests__/tenant-table-pagination.test.tsx +2 -6
- package/src/__tests__/terminal-log-cleanup.test.tsx +0 -1
- package/src/__tests__/transaction-history.test.tsx +190 -238
- package/src/__tests__/trpc-types.test.ts +2 -6
- package/src/__tests__/use-chat.test.ts +1 -3
- package/src/__tests__/use-plugin-setup-chat-stale-closure.test.ts +1 -4
- package/src/__tests__/use-sidecar-bridge.test.tsx +105 -0
- package/src/__tests__/use-webmcp.test.ts +1 -3
- package/src/__tests__/validate-elevenlabs-key.test.ts +2 -1
- package/src/__tests__/verify-page.test.tsx +4 -13
- package/src/__tests__/verify-redirect.test.tsx +2 -6
- package/src/app/(auth)/error.tsx +1 -7
- package/src/app/(auth)/forgot-password/page.tsx +4 -18
- package/src/app/(auth)/login/page.tsx +5 -22
- package/src/app/(auth)/reset-password/page.tsx +2 -12
- package/src/app/(auth)/signup/page.tsx +10 -44
- package/src/app/(auth)/verify/page.tsx +47 -0
- package/src/app/(dashboard)/billing/credits/page.tsx +14 -67
- package/src/app/(dashboard)/billing/error.tsx +2 -10
- package/src/app/(dashboard)/billing/layout.tsx +12 -62
- package/src/app/(dashboard)/billing/payment/page.tsx +17 -68
- package/src/app/(dashboard)/billing/plans/page.tsx +3 -9
- package/src/app/(dashboard)/billing/usage/hosted/page.tsx +8 -25
- package/src/app/(dashboard)/billing/usage/page.tsx +63 -103
- package/src/app/(dashboard)/changesets/[id]/changeset-detail-client.tsx +9 -27
- package/src/app/(dashboard)/changesets/[id]/error.tsx +2 -6
- package/src/app/(dashboard)/changesets/error.tsx +1 -7
- package/src/app/(dashboard)/chat/page.tsx +2 -6
- package/src/app/(dashboard)/dashboard/network/page.tsx +5 -19
- package/src/app/(dashboard)/error.tsx +1 -7
- package/src/app/(dashboard)/layout.tsx +15 -36
- package/src/app/(dashboard)/marketplace/[plugin]/page.tsx +14 -51
- package/src/app/(dashboard)/marketplace/error.tsx +1 -7
- package/src/app/(dashboard)/marketplace/page.tsx +6 -27
- package/src/app/(dashboard)/not-found.tsx +2 -5
- package/src/app/(dashboard)/onboarding/page.tsx +5 -22
- package/src/app/(dashboard)/settings/account/page.tsx +1 -6
- package/src/app/(dashboard)/settings/activity/page.tsx +8 -34
- package/src/app/(dashboard)/settings/api-keys/page.tsx +15 -60
- package/src/app/(dashboard)/settings/brain/page.tsx +9 -31
- package/src/app/(dashboard)/settings/error.tsx +2 -10
- package/src/app/(dashboard)/settings/notifications/page.tsx +2 -6
- package/src/app/(dashboard)/settings/org/page.tsx +13 -56
- package/src/app/(dashboard)/settings/page.tsx +1 -0
- package/src/app/(dashboard)/settings/profile/page.tsx +126 -73
- package/src/app/(dashboard)/settings/providers/page.tsx +21 -78
- package/src/app/(dashboard)/settings/secrets/page.tsx +13 -58
- package/src/app/(dashboard)/settings/security/page.tsx +31 -111
- package/src/app/admin/email-templates/email-templates-client.tsx +15 -58
- package/src/app/admin/error.tsx +1 -7
- package/src/app/admin/fleet-updates/error.tsx +1 -7
- package/src/app/admin/fleet-updates/fleet-updates-client.tsx +10 -50
- package/src/app/admin/layout.tsx +4 -0
- package/src/app/admin/payment-methods/page.tsx +9 -38
- package/src/app/admin/products/error.tsx +2 -7
- package/src/app/admin/products/page.tsx +1 -4
- package/src/app/admin/promotions/[id]/page.tsx +9 -38
- package/src/app/admin/promotions/page.tsx +9 -36
- package/src/app/admin/rate-overrides/page.tsx +9 -45
- package/src/app/auth/callback/[provider]/page.tsx +1 -8
- package/src/app/auth/verify/page.tsx +9 -36
- package/src/app/channels/error.tsx +2 -10
- package/src/app/channels/layout.tsx +9 -0
- package/src/app/channels/page.tsx +8 -20
- package/src/app/channels/setup/[plugin]/page.tsx +3 -5
- package/src/app/error.tsx +1 -7
- package/src/app/fleet/error.tsx +1 -7
- package/src/app/fleet/layout.tsx +5 -0
- package/src/app/fleet/settings/page.tsx +1 -3
- package/src/app/global-error.tsx +2 -10
- package/src/app/globals.css +1 -4
- package/src/app/instances/[id]/instance-detail-client.tsx +51 -125
- package/src/app/instances/error.tsx +2 -10
- package/src/app/instances/instance-list-client.tsx +20 -69
- package/src/app/instances/layout.tsx +9 -0
- package/src/app/instances/new/create-instance-client.tsx +10 -31
- package/src/app/layout.tsx +2 -10
- package/src/app/not-found.tsx +1 -3
- package/src/app/page.tsx +1 -2
- package/src/app/plugins/error.tsx +2 -10
- package/src/app/plugins/layout.tsx +5 -0
- package/src/app/plugins/page.tsx +16 -48
- package/src/app/pricing/error.tsx +1 -7
- package/src/app/privacy/page.tsx +93 -150
- package/src/app/status/error.tsx +1 -7
- package/src/app/terms/page.tsx +89 -144
- package/src/components/account-switcher.tsx +25 -52
- package/src/components/admin/accounting-dashboard.tsx +1 -3
- package/src/components/admin/admin-guard.tsx +1 -3
- package/src/components/admin/admin-nav.tsx +1 -3
- package/src/components/admin/affiliate-dashboard.tsx +25 -94
- package/src/components/admin/audit-log-table.tsx +13 -49
- package/src/components/admin/billing-health-dashboard.tsx +7 -25
- package/src/components/admin/bulk-actions-bar.test.tsx +1 -7
- package/src/components/admin/bulk-actions-bar.tsx +1 -3
- package/src/components/admin/bulk-export-dialog.test.tsx +1 -7
- package/src/components/admin/bulk-export-dialog.tsx +6 -32
- package/src/components/admin/bulk-grant-dialog.test.tsx +2 -6
- package/src/components/admin/bulk-grant-dialog.tsx +4 -15
- package/src/components/admin/bulk-preview-dialog.tsx +3 -12
- package/src/components/admin/bulk-reactivate-dialog.tsx +1 -7
- package/src/components/admin/bulk-select-all-banner.tsx +1 -6
- package/src/components/admin/bulk-suspend-dialog.tsx +5 -12
- package/src/components/admin/bulk-undo-toast.tsx +1 -2
- package/src/components/admin/compliance-dashboard.tsx +31 -101
- package/src/components/admin/gpu-dashboard.tsx +21 -70
- package/src/components/admin/grant-credits-dialog.tsx +4 -17
- package/src/components/admin/incident-dashboard.tsx +10 -25
- package/src/components/admin/inference-dashboard.tsx +14 -54
- package/src/components/admin/marketplace-admin.tsx +18 -60
- package/src/components/admin/migrations-dashboard.tsx +9 -42
- package/src/components/admin/onboarding-dashboard.tsx +14 -64
- package/src/components/admin/pool-config-dashboard.tsx +4 -10
- package/src/components/admin/products/fleet-form.tsx +2 -11
- package/src/components/admin/products/nav-editor.tsx +3 -10
- package/src/components/admin/promotions/promotion-form.tsx +9 -42
- package/src/components/admin/roles-dashboard.tsx +7 -34
- package/src/components/admin/suspend-dialog.tsx +4 -11
- package/src/components/admin/tenant-notes-panel.tsx +1 -3
- package/src/components/admin/tenant-row-actions.tsx +4 -20
- package/src/components/admin/tenant-table.tsx +12 -49
- package/src/components/auth/auth-redirect.tsx +11 -3
- package/src/components/auth/email-verification-result-banner.tsx +1 -3
- package/src/components/auth/resend-verification-button.tsx +2 -10
- package/src/components/auth/wopr-wordmark.tsx +1 -3
- package/src/components/billing/add-payment-method-dialog.tsx +1 -2
- package/src/components/billing/affiliate-dashboard.tsx +4 -16
- package/src/components/billing/amount-selector.tsx +1 -3
- package/src/components/billing/auto-topup-card.tsx +2 -11
- package/src/components/billing/buy-credits-panel.tsx +4 -14
- package/src/components/billing/byok-callout.tsx +6 -8
- package/src/components/billing/confirmation-tracker.tsx +4 -14
- package/src/components/billing/credit-balance-badge.tsx +22 -0
- package/src/components/billing/credit-balance.tsx +3 -9
- package/src/components/billing/crypto-checkout.tsx +5 -24
- package/src/components/billing/degraded-state-banner.tsx +1 -3
- package/src/components/billing/deposit-view.tsx +301 -41
- package/src/components/billing/dividend-banner.tsx +1 -3
- package/src/components/billing/dividend-eligibility.tsx +3 -12
- package/src/components/billing/dividend-pool-stats.tsx +6 -20
- package/src/components/billing/first-dividend-dialog.tsx +2 -2
- package/src/components/billing/org-billing-page.tsx +8 -31
- package/src/components/billing/payment-method-picker.tsx +2 -10
- package/src/components/billing/suspension-banner.tsx +2 -7
- package/src/components/billing/transaction-history.tsx +10 -58
- package/src/components/billing/unified-checkout.tsx +547 -0
- package/src/components/bot-settings/backups-tab.tsx +9 -33
- package/src/components/bot-settings/bot-settings-client.tsx +32 -134
- package/src/components/bot-settings/resources-tab.tsx +2 -9
- package/src/components/bot-settings/storage-tab.tsx +19 -48
- package/src/components/bot-settings/vps-info-panel.tsx +3 -11
- package/src/components/bot-settings/vps-upgrade-card.tsx +3 -4
- package/src/components/brand-hydrator.tsx +13 -0
- package/src/components/channel-wizard/field-interactive.tsx +1 -3
- package/src/components/channel-wizard/field-qr.tsx +10 -39
- package/src/components/channel-wizard/step-renderer.tsx +5 -28
- package/src/components/channel-wizard/wizard.tsx +6 -31
- package/src/components/chat/chat-message.tsx +1 -4
- package/src/components/chat/chat-panel.tsx +4 -18
- package/src/components/chat/chat-widget.tsx +3 -14
- package/src/components/dashboard/command-center.tsx +15 -61
- package/src/components/fleet/update-settings-card.tsx +7 -23
- package/src/components/instance-update-banner.tsx +130 -0
- package/src/components/instances/friends-tab.test.tsx +2 -9
- package/src/components/instances/friends-tab.tsx +18 -74
- package/src/components/instances/update-available-badge.tsx +2 -11
- package/src/components/landing/hero.tsx +3 -9
- package/src/components/landing/landing-page.tsx +1 -3
- package/src/components/landing/portfolio-chart.tsx +4 -9
- package/src/components/landing/story-sections.tsx +1 -3
- package/src/components/landing/terminal-sequence.tsx +4 -17
- package/src/components/marketplace/empty-state.tsx +2 -6
- package/src/components/marketplace/first-visit-hero.tsx +1 -3
- package/src/components/marketplace/install-wizard.tsx +20 -77
- package/src/components/marketplace/marketplace-tabs.tsx +1 -4
- package/src/components/marketplace/plugin-card.tsx +2 -9
- package/src/components/marketplace/superpower-content.tsx +1 -3
- package/src/components/marketplace/terminal-search.tsx +2 -8
- package/src/components/oauth-buttons.tsx +29 -14
- package/src/components/observability/fleet-health.tsx +5 -18
- package/src/components/observability/health-overview.tsx +7 -20
- package/src/components/observability/logs-viewer.tsx +8 -32
- package/src/components/observability/metrics-dashboard.tsx +2 -15
- package/src/components/onboarding/fallback-setup.tsx +6 -25
- package/src/components/onboarding/setup-checklist.tsx +18 -51
- package/src/components/onboarding/step-superpowers.tsx +1 -4
- package/src/components/plugin-setup/setup-chat-panel.tsx +6 -22
- package/src/components/pricing/dividend-calculator.tsx +6 -12
- package/src/components/pricing/dividend-stats.tsx +5 -17
- package/src/components/pricing/pricing-page.tsx +17 -36
- package/src/components/settings/create-org-wizard.tsx +2 -5
- package/src/components/sidebar.tsx +7 -42
- package/src/components/sidecar-frame.tsx +78 -0
- package/src/components/status/status-page.tsx +6 -28
- package/src/components/ui/alert-dialog.tsx +8 -25
- package/src/components/ui/badge.tsx +2 -8
- package/src/components/ui/banner.tsx +1 -6
- package/src/components/ui/card.tsx +5 -24
- package/src/components/ui/checkbox.tsx +1 -5
- package/src/components/ui/collapsible.tsx +3 -8
- package/src/components/ui/dialog.tsx +4 -10
- package/src/components/ui/dropdown-menu.tsx +9 -18
- package/src/components/ui/form.tsx +2 -16
- package/src/components/ui/popover.tsx +3 -23
- package/src/components/ui/progress.tsx +1 -5
- package/src/components/ui/radio-group.tsx +3 -15
- package/src/components/ui/select.tsx +4 -17
- package/src/components/ui/sheet.tsx +5 -19
- package/src/components/ui/skeleton.tsx +1 -7
- package/src/components/ui/table.tsx +5 -22
- package/src/components/ui/tabs.tsx +3 -13
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/components/unified-sidebar.tsx +493 -0
- package/src/hooks/__tests__/use-fleet-sse.test.ts +1 -4
- package/src/hooks/__tests__/use-save-queue.test.ts +2 -8
- package/src/hooks/use-credit-balance.ts +27 -0
- package/src/hooks/use-my-org-role.ts +1 -3
- package/src/hooks/use-plugin-registry.ts +8 -14
- package/src/hooks/use-plugin-setup-chat.ts +2 -5
- package/src/hooks/use-sidecar-bridge.tsx +148 -0
- package/src/hooks/use-webmcp.ts +1 -4
- package/src/lib/__tests__/admin-api.test.ts +1 -3
- package/src/lib/__tests__/api-bot-crud.test.ts +8 -18
- package/src/lib/__tests__/api-fetch.test.ts +4 -16
- package/src/lib/__tests__/org-billing-api.test.ts +1 -3
- package/src/lib/__tests__/pricing-data.test.ts +0 -8
- package/src/lib/__tests__/settings-api.test.ts +1 -3
- package/src/lib/admin-affiliate-api.ts +2 -7
- package/src/lib/admin-api.ts +6 -26
- package/src/lib/admin-incident-api.ts +11 -19
- package/src/lib/admin-marketplace-api.ts +1 -5
- package/src/lib/api-config.test.ts +5 -50
- package/src/lib/api.ts +143 -122
- package/src/lib/auth-client.ts +1 -2
- package/src/lib/bot-settings-data.ts +11 -36
- package/src/lib/brand-config.ts +56 -115
- package/src/lib/brand.ts +2 -15
- package/src/lib/chat/use-chat.ts +2 -7
- package/src/lib/cost-comparison-data.test.ts +1 -3
- package/src/lib/cost-comparison-data.ts +1 -4
- package/src/lib/errors.ts +1 -4
- package/src/lib/fetch-utils.test.ts +26 -9
- package/src/lib/fetch-utils.ts +40 -11
- package/src/lib/logger.ts +2 -0
- package/src/lib/marketplace-data.ts +3 -11
- package/src/lib/oauth-errors.ts +2 -4
- package/src/lib/onboarding-data.ts +3 -11
- package/src/lib/org-api.ts +2 -10
- package/src/lib/org-billing-api.ts +5 -19
- package/src/lib/plugin/tool-definitions.ts +1 -2
- package/src/lib/require-auth.ts +57 -0
- package/src/lib/settings-api.ts +1 -4
- package/src/lib/sidecar-routes.ts +43 -0
- package/src/lib/trpc-server.ts +49 -0
- package/src/lib/trpc-types.ts +4 -6
- package/src/lib/trpc.tsx +12 -4
- package/src/lib/validate-redirect-url.ts +1 -4
- package/src/lib/webmcp/marketplace-onboarding-tools.ts +6 -16
- package/src/lib/webmcp/register.ts +1 -4
- package/src/lib/webmcp/tools.ts +2 -9
- package/src/proxy.ts +35 -212
- package/src/types/missing-deps.d.ts +2 -8
- package/tsconfig.json +1 -8
- package/biome.json +0 -52
- package/src/__tests__/__snapshots__/layout-snapshots.test.tsx.snap +0 -741
- package/src/__tests__/billing-byok-callout.test.tsx +0 -76
- package/src/lib/__tests__/__snapshots__/pricing-data.test.ts.snap +0 -112
|
@@ -26,9 +26,7 @@ vi.mock("@/lib/api", () => ({
|
|
|
26
26
|
}));
|
|
27
27
|
|
|
28
28
|
// Mock bot-settings-data with controlBot we can spy on
|
|
29
|
-
const mockControlBot = vi
|
|
30
|
-
.fn()
|
|
31
|
-
.mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 100)));
|
|
29
|
+
const mockControlBot = vi.fn().mockImplementation(() => new Promise((resolve) => setTimeout(resolve, 100)));
|
|
32
30
|
const mockGetBotSettings = vi.fn().mockResolvedValue({
|
|
33
31
|
id: "bot-1",
|
|
34
32
|
identity: { name: "Test Bot", personality: "", avatar: "" },
|
|
@@ -335,9 +335,7 @@ describe("Channels tab", () => {
|
|
|
335
335
|
|
|
336
336
|
await user.click(screen.getByRole("tab", { name: "Channels" }));
|
|
337
337
|
|
|
338
|
-
expect(
|
|
339
|
-
screen.getByText("Your Platform works everywhere you do. All channels are free."),
|
|
340
|
-
).toBeInTheDocument();
|
|
338
|
+
expect(screen.getByText("Your Platform works everywhere you do. All channels are free.")).toBeInTheDocument();
|
|
341
339
|
});
|
|
342
340
|
});
|
|
343
341
|
|
|
@@ -610,9 +608,7 @@ describe("Danger Zone tab", () => {
|
|
|
610
608
|
describe("Error handling", () => {
|
|
611
609
|
it("shows error when getBotSettings fails", async () => {
|
|
612
610
|
const { getBotSettings } = await import("@/lib/bot-settings-data");
|
|
613
|
-
vi.mocked(getBotSettings).mockRejectedValueOnce(
|
|
614
|
-
new Error("API error: 500 Internal Server Error"),
|
|
615
|
-
);
|
|
611
|
+
vi.mocked(getBotSettings).mockRejectedValueOnce(new Error("API error: 500 Internal Server Error"));
|
|
616
612
|
const { BotSettingsClient } = await import("../components/bot-settings/bot-settings-client");
|
|
617
613
|
render(<BotSettingsClient botId="bot-001" />);
|
|
618
614
|
expect(await screen.findByText("API error: 500 Internal Server Error")).toBeInTheDocument();
|
|
@@ -78,15 +78,7 @@ describe("Brand Bible", () => {
|
|
|
78
78
|
|
|
79
79
|
describe("Emotional arc", () => {
|
|
80
80
|
it("defines feelings for all major page types", () => {
|
|
81
|
-
const pages = [
|
|
82
|
-
"landing",
|
|
83
|
-
"onboarding",
|
|
84
|
-
"dashboard",
|
|
85
|
-
"marketplace",
|
|
86
|
-
"billing",
|
|
87
|
-
"settings",
|
|
88
|
-
"fleet",
|
|
89
|
-
] as const;
|
|
81
|
+
const pages = ["landing", "onboarding", "dashboard", "marketplace", "billing", "settings", "fleet"] as const;
|
|
90
82
|
for (const page of pages) {
|
|
91
83
|
expect(typeof emotionalArc[page].feel).toBe("string");
|
|
92
84
|
expect(typeof emotionalArc[page].job).toBe("string");
|
|
@@ -116,9 +108,9 @@ describe("Brand Bible", () => {
|
|
|
116
108
|
expect(DOMAIN).toBe("localhost");
|
|
117
109
|
});
|
|
118
110
|
|
|
119
|
-
it("has a tagline", () => {
|
|
111
|
+
it("has a tagline (may be empty in default brand config)", () => {
|
|
120
112
|
expect(typeof TAGLINE).toBe("string");
|
|
121
|
-
|
|
113
|
+
// Default brand config has empty tagline; specific brand deployments set it
|
|
122
114
|
});
|
|
123
115
|
|
|
124
116
|
it("defines the price from brand config", () => {
|
|
@@ -242,16 +234,12 @@ describe("Brand Bible", () => {
|
|
|
242
234
|
});
|
|
243
235
|
|
|
244
236
|
it("includes product name usage examples", () => {
|
|
245
|
-
const hasNameExample = copyExamples.some(
|
|
246
|
-
(e) => e.do.includes("Platform") || e.rule.includes("Platform"),
|
|
247
|
-
);
|
|
237
|
+
const hasNameExample = copyExamples.some((e) => e.do.includes("Platform") || e.rule.includes("Platform"));
|
|
248
238
|
expect(hasNameExample).toBe(true);
|
|
249
239
|
});
|
|
250
240
|
|
|
251
241
|
it("includes supercomputer angle", () => {
|
|
252
|
-
const hasSupercomputer = copyExamples.some((e) =>
|
|
253
|
-
e.do.toLowerCase().includes("supercomputer"),
|
|
254
|
-
);
|
|
242
|
+
const hasSupercomputer = copyExamples.some((e) => e.do.toLowerCase().includes("supercomputer"));
|
|
255
243
|
expect(hasSupercomputer).toBe(true);
|
|
256
244
|
});
|
|
257
245
|
});
|
|
@@ -304,15 +292,7 @@ describe("Brand Bible", () => {
|
|
|
304
292
|
|
|
305
293
|
describe("Copy frameworks", () => {
|
|
306
294
|
it("defines frameworks for all page types", () => {
|
|
307
|
-
const pages = [
|
|
308
|
-
"landing",
|
|
309
|
-
"onboarding",
|
|
310
|
-
"dashboard",
|
|
311
|
-
"marketplace",
|
|
312
|
-
"billing",
|
|
313
|
-
"settings",
|
|
314
|
-
"empty",
|
|
315
|
-
] as const;
|
|
295
|
+
const pages = ["landing", "onboarding", "dashboard", "marketplace", "billing", "settings", "empty"] as const;
|
|
316
296
|
for (const page of pages) {
|
|
317
297
|
expect(typeof copyFrameworks[page].headline).toBe("string");
|
|
318
298
|
}
|
|
@@ -100,9 +100,7 @@ describe("BuyCreditsPanel", () => {
|
|
|
100
100
|
mockGetCreditOptions.mockResolvedValue([]);
|
|
101
101
|
render(<BuyCreditsPanel />);
|
|
102
102
|
|
|
103
|
-
expect(
|
|
104
|
-
await screen.findByText("Credit purchases are not available at this time."),
|
|
105
|
-
).toBeInTheDocument();
|
|
103
|
+
expect(await screen.findByText("Credit purchases are not available at this time.")).toBeInTheDocument();
|
|
106
104
|
// Should NOT show retry button for intentionally empty tiers
|
|
107
105
|
expect(screen.queryByRole("button", { name: "Try again" })).not.toBeInTheDocument();
|
|
108
106
|
});
|
|
@@ -2,13 +2,11 @@ import { render, screen, waitFor } from "@testing-library/react";
|
|
|
2
2
|
import userEvent from "@testing-library/user-event";
|
|
3
3
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
4
4
|
|
|
5
|
-
const { mockCreateCheckout, mockGetSupportedPaymentMethods, mockGetChargeStatus } = vi.hoisted(
|
|
6
|
-
()
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}),
|
|
11
|
-
);
|
|
5
|
+
const { mockCreateCheckout, mockGetSupportedPaymentMethods, mockGetChargeStatus } = vi.hoisted(() => ({
|
|
6
|
+
mockCreateCheckout: vi.fn(),
|
|
7
|
+
mockGetSupportedPaymentMethods: vi.fn(),
|
|
8
|
+
mockGetChargeStatus: vi.fn(),
|
|
9
|
+
}));
|
|
12
10
|
|
|
13
11
|
vi.mock("@/lib/api", () => ({
|
|
14
12
|
createCheckout: (...args: unknown[]) => mockCreateCheckout(...args),
|
|
@@ -17,6 +15,7 @@ vi.mock("@/lib/api", () => ({
|
|
|
17
15
|
}));
|
|
18
16
|
|
|
19
17
|
vi.mock("framer-motion", () => ({
|
|
18
|
+
AnimatePresence: ({ children }: React.PropsWithChildren<Record<string, unknown>>) => <>{children}</>,
|
|
20
19
|
motion: {
|
|
21
20
|
button: ({
|
|
22
21
|
children,
|
|
@@ -51,28 +50,28 @@ vi.mock("better-auth/react", () => ({
|
|
|
51
50
|
}),
|
|
52
51
|
}));
|
|
53
52
|
|
|
54
|
-
vi.mock("
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
...actual,
|
|
58
|
-
Bitcoin: () => <span data-testid="bitcoin-icon" />,
|
|
59
|
-
};
|
|
60
|
-
});
|
|
53
|
+
vi.mock("qrcode.react", () => ({
|
|
54
|
+
QRCodeSVG: () => <div data-testid="qr-code" />,
|
|
55
|
+
}));
|
|
61
56
|
|
|
62
57
|
const MOCK_USDC_METHOD = {
|
|
63
58
|
id: "usdc:base",
|
|
64
59
|
type: "erc20",
|
|
65
|
-
label: "USDC on Base",
|
|
66
60
|
token: "USDC",
|
|
67
61
|
chain: "base",
|
|
62
|
+
displayName: "USDC on Base",
|
|
63
|
+
decimals: 6,
|
|
64
|
+
displayOrder: 1,
|
|
68
65
|
iconUrl: "https://example.com/usdc.svg",
|
|
69
66
|
};
|
|
70
67
|
const MOCK_ETH_METHOD = {
|
|
71
68
|
id: "eth:base",
|
|
72
69
|
type: "native",
|
|
73
|
-
label: "ETH on Base",
|
|
74
70
|
token: "ETH",
|
|
75
71
|
chain: "base",
|
|
72
|
+
displayName: "ETH on Base",
|
|
73
|
+
decimals: 18,
|
|
74
|
+
displayOrder: 2,
|
|
76
75
|
iconUrl: "https://example.com/eth.svg",
|
|
77
76
|
};
|
|
78
77
|
|
|
@@ -98,40 +97,61 @@ describe("BuyCryptoCreditPanel", () => {
|
|
|
98
97
|
expect(screen.getByText("$100")).toBeInTheDocument();
|
|
99
98
|
});
|
|
100
99
|
|
|
101
|
-
it("
|
|
100
|
+
it("Continue button is disabled when no amount selected", async () => {
|
|
102
101
|
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD, MOCK_ETH_METHOD]);
|
|
103
102
|
const { BuyCryptoCreditPanel } = await import("../components/billing/buy-crypto-credits-panel");
|
|
104
103
|
render(<BuyCryptoCreditPanel />);
|
|
105
104
|
|
|
106
105
|
await waitFor(() => {
|
|
107
|
-
expect(screen.getByText("
|
|
106
|
+
expect(screen.getByText("Pay with Crypto")).toBeInTheDocument();
|
|
108
107
|
});
|
|
109
108
|
|
|
110
|
-
const
|
|
111
|
-
expect(
|
|
109
|
+
const continueBtn = screen.getByRole("button", { name: "Continue to payment" });
|
|
110
|
+
expect(continueBtn).toBeDisabled();
|
|
112
111
|
});
|
|
113
112
|
|
|
114
|
-
it("
|
|
113
|
+
it("Continue button is enabled after selecting an amount", async () => {
|
|
115
114
|
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD, MOCK_ETH_METHOD]);
|
|
116
115
|
const user = userEvent.setup();
|
|
117
116
|
const { BuyCryptoCreditPanel } = await import("../components/billing/buy-crypto-credits-panel");
|
|
118
117
|
render(<BuyCryptoCreditPanel />);
|
|
119
118
|
|
|
120
119
|
await waitFor(() => {
|
|
121
|
-
expect(screen.getByText("
|
|
120
|
+
expect(screen.getByText("Pay with Crypto")).toBeInTheDocument();
|
|
122
121
|
});
|
|
123
122
|
|
|
124
123
|
await user.click(screen.getByText("$25"));
|
|
125
|
-
expect(screen.getByRole("button", { name: "
|
|
124
|
+
expect(screen.getByRole("button", { name: "Continue to payment" })).toBeEnabled();
|
|
126
125
|
});
|
|
127
126
|
|
|
128
|
-
it("
|
|
127
|
+
it("shows payment method picker after selecting amount", async () => {
|
|
129
128
|
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD, MOCK_ETH_METHOD]);
|
|
129
|
+
const user = userEvent.setup();
|
|
130
|
+
const { BuyCryptoCreditPanel } = await import("../components/billing/buy-crypto-credits-panel");
|
|
131
|
+
render(<BuyCryptoCreditPanel />);
|
|
132
|
+
|
|
133
|
+
await waitFor(() => {
|
|
134
|
+
expect(screen.getByText("Pay with Crypto")).toBeInTheDocument();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
await user.click(screen.getByText("$50"));
|
|
138
|
+
await user.click(screen.getByRole("button", { name: "Continue to payment" }));
|
|
139
|
+
|
|
140
|
+
await waitFor(() => {
|
|
141
|
+
expect(screen.getByText("USDC on Base")).toBeInTheDocument();
|
|
142
|
+
});
|
|
143
|
+
expect(screen.getByText("ETH on Base")).toBeInTheDocument();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("calls createCheckout and shows deposit address", async () => {
|
|
147
|
+
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD]);
|
|
130
148
|
mockCreateCheckout.mockResolvedValue({
|
|
131
149
|
depositAddress: "0xabc123def456",
|
|
132
150
|
displayAmount: "50.000000 USDC",
|
|
151
|
+
amountUsd: 50,
|
|
133
152
|
token: "USDC",
|
|
134
153
|
chain: "base",
|
|
154
|
+
referenceId: "ref-123",
|
|
135
155
|
});
|
|
136
156
|
|
|
137
157
|
const user = userEvent.setup();
|
|
@@ -139,19 +159,27 @@ describe("BuyCryptoCreditPanel", () => {
|
|
|
139
159
|
render(<BuyCryptoCreditPanel />);
|
|
140
160
|
|
|
141
161
|
await waitFor(() => {
|
|
142
|
-
expect(screen.getByText("
|
|
162
|
+
expect(screen.getByText("Pay with Crypto")).toBeInTheDocument();
|
|
143
163
|
});
|
|
144
164
|
|
|
145
165
|
await user.click(screen.getByText("$50"));
|
|
146
|
-
await user.click(screen.getByRole("button", { name: "
|
|
166
|
+
await user.click(screen.getByRole("button", { name: "Continue to payment" }));
|
|
167
|
+
|
|
168
|
+
await waitFor(() => {
|
|
169
|
+
expect(screen.getByText("USDC on Base")).toBeInTheDocument();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
await user.click(screen.getByText("USDC on Base"));
|
|
147
173
|
|
|
148
174
|
expect(mockCreateCheckout).toHaveBeenCalledWith("usdc:base", 50);
|
|
149
|
-
|
|
175
|
+
await waitFor(() => {
|
|
176
|
+
expect(screen.getByText("0xabc123def456")).toBeInTheDocument();
|
|
177
|
+
});
|
|
150
178
|
expect(screen.getByText("50.000000 USDC")).toBeInTheDocument();
|
|
151
179
|
});
|
|
152
180
|
|
|
153
181
|
it("shows Creating checkout... while checkout is in progress", async () => {
|
|
154
|
-
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD
|
|
182
|
+
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD]);
|
|
155
183
|
mockCreateCheckout.mockReturnValue(
|
|
156
184
|
new Promise(() => {
|
|
157
185
|
/* intentionally pending */
|
|
@@ -163,31 +191,21 @@ describe("BuyCryptoCreditPanel", () => {
|
|
|
163
191
|
render(<BuyCryptoCreditPanel />);
|
|
164
192
|
|
|
165
193
|
await waitFor(() => {
|
|
166
|
-
expect(screen.getByText("
|
|
194
|
+
expect(screen.getByText("Pay with Crypto")).toBeInTheDocument();
|
|
167
195
|
});
|
|
168
196
|
|
|
169
197
|
await user.click(screen.getByText("$50"));
|
|
170
|
-
await user.click(screen.getByRole("button", { name: "
|
|
171
|
-
|
|
172
|
-
expect(await screen.findByText("Creating checkout...")).toBeInTheDocument();
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it("shows error when checkout API call fails", async () => {
|
|
176
|
-
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD, MOCK_ETH_METHOD]);
|
|
177
|
-
mockCreateCheckout.mockRejectedValue(new Error("API down"));
|
|
178
|
-
|
|
179
|
-
const user = userEvent.setup();
|
|
180
|
-
const { BuyCryptoCreditPanel } = await import("../components/billing/buy-crypto-credits-panel");
|
|
181
|
-
render(<BuyCryptoCreditPanel />);
|
|
198
|
+
await user.click(screen.getByRole("button", { name: "Continue to payment" }));
|
|
182
199
|
|
|
183
200
|
await waitFor(() => {
|
|
184
|
-
expect(screen.getByText("USDC")).toBeInTheDocument();
|
|
201
|
+
expect(screen.getByText("USDC on Base")).toBeInTheDocument();
|
|
185
202
|
});
|
|
186
203
|
|
|
187
|
-
await user.click(screen.getByText("
|
|
188
|
-
await user.click(screen.getByRole("button", { name: "Pay with USDC" }));
|
|
204
|
+
await user.click(screen.getByText("USDC on Base"));
|
|
189
205
|
|
|
190
|
-
|
|
206
|
+
await waitFor(() => {
|
|
207
|
+
expect(screen.getByText("Creating checkout...")).toBeInTheDocument();
|
|
208
|
+
});
|
|
191
209
|
});
|
|
192
210
|
|
|
193
211
|
it("hides panel when no payment methods available", async () => {
|
|
@@ -195,95 +213,40 @@ describe("BuyCryptoCreditPanel", () => {
|
|
|
195
213
|
const { BuyCryptoCreditPanel } = await import("../components/billing/buy-crypto-credits-panel");
|
|
196
214
|
const { container } = render(<BuyCryptoCreditPanel />);
|
|
197
215
|
|
|
198
|
-
// Component returns null when no methods
|
|
199
216
|
await waitFor(() => {
|
|
200
217
|
expect(container.innerHTML).toBe("");
|
|
201
218
|
});
|
|
202
219
|
});
|
|
203
220
|
|
|
204
|
-
it("
|
|
221
|
+
it("renders icon for each payment method in picker", async () => {
|
|
205
222
|
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD, MOCK_ETH_METHOD]);
|
|
206
223
|
const user = userEvent.setup();
|
|
207
224
|
const { BuyCryptoCreditPanel } = await import("../components/billing/buy-crypto-credits-panel");
|
|
208
225
|
render(<BuyCryptoCreditPanel />);
|
|
209
226
|
|
|
210
227
|
await waitFor(() => {
|
|
211
|
-
expect(screen.getByText("
|
|
228
|
+
expect(screen.getByText("Pay with Crypto")).toBeInTheDocument();
|
|
212
229
|
});
|
|
213
230
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// Switch to ETH
|
|
218
|
-
await user.click(screen.getByText("ETH"));
|
|
219
|
-
expect(screen.getByRole("button", { name: "Pay with ETH" })).toBeInTheDocument();
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it("renders icon for each payment method", async () => {
|
|
223
|
-
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD, MOCK_ETH_METHOD]);
|
|
224
|
-
const { BuyCryptoCreditPanel } = await import("../components/billing/buy-crypto-credits-panel");
|
|
225
|
-
render(<BuyCryptoCreditPanel />);
|
|
231
|
+
await user.click(screen.getByText("$25"));
|
|
232
|
+
await user.click(screen.getByRole("button", { name: "Continue to payment" }));
|
|
226
233
|
|
|
227
234
|
await waitFor(() => {
|
|
228
|
-
expect(screen.getByText("USDC")).toBeInTheDocument();
|
|
235
|
+
expect(screen.getByText("USDC on Base")).toBeInTheDocument();
|
|
229
236
|
});
|
|
230
237
|
|
|
231
238
|
const icons = screen.getAllByRole("img");
|
|
232
|
-
expect(icons).
|
|
239
|
+
expect(icons.length).toBeGreaterThanOrEqual(2);
|
|
233
240
|
expect(icons[0]).toHaveAttribute("src", "https://example.com/usdc.svg");
|
|
234
241
|
expect(icons[1]).toHaveAttribute("src", "https://example.com/eth.svg");
|
|
235
242
|
});
|
|
236
243
|
|
|
237
|
-
it("shows
|
|
238
|
-
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD]);
|
|
239
|
-
mockCreateCheckout.mockResolvedValue({
|
|
240
|
-
depositAddress: "0xabc123",
|
|
241
|
-
displayAmount: "50.000000 USDC",
|
|
242
|
-
token: "USDC",
|
|
243
|
-
chain: "base",
|
|
244
|
-
referenceId: "ref-123",
|
|
245
|
-
});
|
|
246
|
-
mockGetChargeStatus.mockResolvedValue({
|
|
247
|
-
chargeId: "ch-1",
|
|
248
|
-
status: "partial",
|
|
249
|
-
amountExpectedCents: 5000,
|
|
250
|
-
amountReceivedCents: 2500,
|
|
251
|
-
confirmations: 0,
|
|
252
|
-
confirmationsRequired: 6,
|
|
253
|
-
credited: false,
|
|
254
|
-
amountUsdCents: 5000,
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
const user = userEvent.setup();
|
|
258
|
-
vi.useFakeTimers({ shouldAdvanceTime: true });
|
|
259
|
-
const { BuyCryptoCreditPanel } = await import("../components/billing/buy-crypto-credits-panel");
|
|
260
|
-
render(<BuyCryptoCreditPanel />);
|
|
261
|
-
|
|
262
|
-
await waitFor(() => {
|
|
263
|
-
expect(screen.getByText("USDC")).toBeInTheDocument();
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
await user.click(screen.getByText("$50"));
|
|
267
|
-
await user.click(screen.getByRole("button", { name: "Pay with USDC" }));
|
|
268
|
-
|
|
269
|
-
await waitFor(() => {
|
|
270
|
-
expect(screen.getByText("0xabc123")).toBeInTheDocument();
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
vi.advanceTimersByTime(5000);
|
|
274
|
-
|
|
275
|
-
await waitFor(() => {
|
|
276
|
-
expect(screen.getByText(/Received \$25\.00 of \$50\.00/)).toBeInTheDocument();
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
vi.useRealTimers();
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it("shows confirmation progress", async () => {
|
|
244
|
+
it("shows confirmation progress after payment received", async () => {
|
|
283
245
|
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD]);
|
|
284
246
|
mockCreateCheckout.mockResolvedValue({
|
|
285
247
|
depositAddress: "0xabc123",
|
|
286
248
|
displayAmount: "50.000000 USDC",
|
|
249
|
+
amountUsd: 50,
|
|
287
250
|
token: "USDC",
|
|
288
251
|
chain: "base",
|
|
289
252
|
referenceId: "ref-456",
|
|
@@ -305,11 +268,17 @@ describe("BuyCryptoCreditPanel", () => {
|
|
|
305
268
|
render(<BuyCryptoCreditPanel />);
|
|
306
269
|
|
|
307
270
|
await waitFor(() => {
|
|
308
|
-
expect(screen.getByText("
|
|
271
|
+
expect(screen.getByText("Pay with Crypto")).toBeInTheDocument();
|
|
309
272
|
});
|
|
310
273
|
|
|
311
274
|
await user.click(screen.getByText("$50"));
|
|
312
|
-
await user.click(screen.getByRole("button", { name: "
|
|
275
|
+
await user.click(screen.getByRole("button", { name: "Continue to payment" }));
|
|
276
|
+
|
|
277
|
+
await waitFor(() => {
|
|
278
|
+
expect(screen.getByText("USDC on Base")).toBeInTheDocument();
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
await user.click(screen.getByText("USDC on Base"));
|
|
313
282
|
|
|
314
283
|
await waitFor(() => {
|
|
315
284
|
expect(screen.getByText("0xabc123")).toBeInTheDocument();
|
|
@@ -318,17 +287,18 @@ describe("BuyCryptoCreditPanel", () => {
|
|
|
318
287
|
vi.advanceTimersByTime(5000);
|
|
319
288
|
|
|
320
289
|
await waitFor(() => {
|
|
321
|
-
expect(screen.getByText(
|
|
290
|
+
expect(screen.getByText("3 / 6")).toBeInTheDocument();
|
|
322
291
|
});
|
|
323
292
|
|
|
324
293
|
vi.useRealTimers();
|
|
325
294
|
});
|
|
326
295
|
|
|
327
|
-
it("shows
|
|
296
|
+
it("shows expired status", async () => {
|
|
328
297
|
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_USDC_METHOD]);
|
|
329
298
|
mockCreateCheckout.mockResolvedValue({
|
|
330
299
|
depositAddress: "0xabc123",
|
|
331
300
|
displayAmount: "50.000000 USDC",
|
|
301
|
+
amountUsd: 50,
|
|
332
302
|
token: "USDC",
|
|
333
303
|
chain: "base",
|
|
334
304
|
referenceId: "ref-789",
|
|
@@ -350,11 +320,17 @@ describe("BuyCryptoCreditPanel", () => {
|
|
|
350
320
|
render(<BuyCryptoCreditPanel />);
|
|
351
321
|
|
|
352
322
|
await waitFor(() => {
|
|
353
|
-
expect(screen.getByText("
|
|
323
|
+
expect(screen.getByText("Pay with Crypto")).toBeInTheDocument();
|
|
354
324
|
});
|
|
355
325
|
|
|
356
326
|
await user.click(screen.getByText("$50"));
|
|
357
|
-
await user.click(screen.getByRole("button", { name: "
|
|
327
|
+
await user.click(screen.getByRole("button", { name: "Continue to payment" }));
|
|
328
|
+
|
|
329
|
+
await waitFor(() => {
|
|
330
|
+
expect(screen.getByText("USDC on Base")).toBeInTheDocument();
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
await user.click(screen.getByText("USDC on Base"));
|
|
358
334
|
|
|
359
335
|
await waitFor(() => {
|
|
360
336
|
expect(screen.getByText("0xabc123")).toBeInTheDocument();
|
|
@@ -363,18 +339,18 @@ describe("BuyCryptoCreditPanel", () => {
|
|
|
363
339
|
vi.advanceTimersByTime(5000);
|
|
364
340
|
|
|
365
341
|
await waitFor(() => {
|
|
366
|
-
expect(screen.getByText("Payment expired
|
|
342
|
+
expect(screen.getByText("Payment expired")).toBeInTheDocument();
|
|
367
343
|
});
|
|
368
|
-
expect(screen.getByRole("button", { name: "Try Again" })).toBeInTheDocument();
|
|
369
344
|
|
|
370
345
|
vi.useRealTimers();
|
|
371
346
|
});
|
|
372
347
|
|
|
373
|
-
it("calls createCheckout with methodId", async () => {
|
|
348
|
+
it("calls createCheckout with correct methodId and amount", async () => {
|
|
374
349
|
mockGetSupportedPaymentMethods.mockResolvedValue([MOCK_ETH_METHOD]);
|
|
375
350
|
mockCreateCheckout.mockResolvedValue({
|
|
376
351
|
depositAddress: "0xdef456",
|
|
377
352
|
displayAmount: "0.05 ETH",
|
|
353
|
+
amountUsd: 100,
|
|
378
354
|
token: "ETH",
|
|
379
355
|
chain: "base",
|
|
380
356
|
referenceId: "ref-eth",
|
|
@@ -385,11 +361,17 @@ describe("BuyCryptoCreditPanel", () => {
|
|
|
385
361
|
render(<BuyCryptoCreditPanel />);
|
|
386
362
|
|
|
387
363
|
await waitFor(() => {
|
|
388
|
-
expect(screen.getByText("
|
|
364
|
+
expect(screen.getByText("Pay with Crypto")).toBeInTheDocument();
|
|
389
365
|
});
|
|
390
366
|
|
|
391
367
|
await user.click(screen.getByText("$100"));
|
|
392
|
-
await user.click(screen.getByRole("button", { name: "
|
|
368
|
+
await user.click(screen.getByRole("button", { name: "Continue to payment" }));
|
|
369
|
+
|
|
370
|
+
await waitFor(() => {
|
|
371
|
+
expect(screen.getByText("ETH on Base")).toBeInTheDocument();
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
await user.click(screen.getByText("ETH on Base"));
|
|
393
375
|
|
|
394
376
|
expect(mockCreateCheckout).toHaveBeenCalledWith("eth:base", 100);
|
|
395
377
|
});
|
|
@@ -2,9 +2,7 @@ import { describe, expect, it } from "vitest";
|
|
|
2
2
|
import type { PluginManifest } from "../lib/marketplace-data";
|
|
3
3
|
import { detectCapabilityConflictsClient } from "../lib/marketplace-data";
|
|
4
4
|
|
|
5
|
-
const makePlugin = (
|
|
6
|
-
overrides: Partial<PluginManifest> & { id: string; name: string },
|
|
7
|
-
): PluginManifest => ({
|
|
5
|
+
const makePlugin = (overrides: Partial<PluginManifest> & { id: string; name: string }): PluginManifest => ({
|
|
8
6
|
description: "",
|
|
9
7
|
version: "1.0.0",
|
|
10
8
|
author: "Test",
|
|
@@ -43,11 +41,7 @@ const allPlugins = [ttsPlugin, sttPlugin, discordPlugin, anotherTts];
|
|
|
43
41
|
|
|
44
42
|
describe("detectCapabilityConflictsClient", () => {
|
|
45
43
|
it("returns empty array when no conflicts", () => {
|
|
46
|
-
const conflicts = detectCapabilityConflictsClient(
|
|
47
|
-
discordPlugin,
|
|
48
|
-
["elevenlabs-tts"],
|
|
49
|
-
allPlugins,
|
|
50
|
-
);
|
|
44
|
+
const conflicts = detectCapabilityConflictsClient(discordPlugin, ["elevenlabs-tts"], allPlugins);
|
|
51
45
|
expect(conflicts).toEqual([]);
|
|
52
46
|
});
|
|
53
47
|
|
|
@@ -101,11 +101,7 @@ describe("CapabilityProviderPicker", () => {
|
|
|
101
101
|
it("renders hosted/BYOK options only for capabilities with hostedProvider", () => {
|
|
102
102
|
const onChoose = vi.fn();
|
|
103
103
|
render(
|
|
104
|
-
<CapabilityProviderPicker
|
|
105
|
-
capabilities={["transcription", "llm", "webhook"]}
|
|
106
|
-
choices={{}}
|
|
107
|
-
onChoose={onChoose}
|
|
108
|
-
/>,
|
|
104
|
+
<CapabilityProviderPicker capabilities={["transcription", "llm", "webhook"]} choices={{}} onChoose={onChoose} />,
|
|
109
105
|
);
|
|
110
106
|
|
|
111
107
|
expect(screen.getByText("Transcription")).toBeInTheDocument();
|
|
@@ -119,13 +115,7 @@ describe("CapabilityProviderPicker", () => {
|
|
|
119
115
|
it("defaults to hosted and calls onChoose when BYOK clicked", async () => {
|
|
120
116
|
const user = userEvent.setup();
|
|
121
117
|
const onChoose = vi.fn();
|
|
122
|
-
render(
|
|
123
|
-
<CapabilityProviderPicker
|
|
124
|
-
capabilities={["transcription"]}
|
|
125
|
-
choices={{}}
|
|
126
|
-
onChoose={onChoose}
|
|
127
|
-
/>,
|
|
128
|
-
);
|
|
118
|
+
render(<CapabilityProviderPicker capabilities={["transcription"]} choices={{}} onChoose={onChoose} />);
|
|
129
119
|
|
|
130
120
|
await user.click(screen.getByText("Use your key"));
|
|
131
121
|
expect(onChoose).toHaveBeenCalledWith("transcription", "byok");
|
|
@@ -5,11 +5,7 @@ import { FieldInteractive } from "@/components/channel-wizard/field-interactive"
|
|
|
5
5
|
import { FieldPaste } from "@/components/channel-wizard/field-paste";
|
|
6
6
|
import { StepRenderer } from "@/components/channel-wizard/step-renderer";
|
|
7
7
|
import type { SetupStep } from "@/lib/channel-manifests";
|
|
8
|
-
import {
|
|
9
|
-
CHANNEL_MANIFESTS_FIXTURE,
|
|
10
|
-
DISCORD_MANIFEST,
|
|
11
|
-
TELEGRAM_MANIFEST,
|
|
12
|
-
} from "./fixtures/mock-manifests";
|
|
8
|
+
import { CHANNEL_MANIFESTS_FIXTURE, DISCORD_MANIFEST, TELEGRAM_MANIFEST } from "./fixtures/mock-manifests";
|
|
13
9
|
|
|
14
10
|
// Mock @/lib/channel-manifests to use fixture data (sync for Wizard component tests)
|
|
15
11
|
vi.mock("@/lib/channel-manifests", async () => {
|
|
@@ -17,9 +13,7 @@ vi.mock("@/lib/channel-manifests", async () => {
|
|
|
17
13
|
return {
|
|
18
14
|
...actual,
|
|
19
15
|
getChannelManifests: vi.fn().mockResolvedValue(CHANNEL_MANIFESTS_FIXTURE),
|
|
20
|
-
getManifest: vi
|
|
21
|
-
.fn()
|
|
22
|
-
.mockImplementation(async (id: string) => CHANNEL_MANIFESTS_FIXTURE.find((m) => m.id === id)),
|
|
16
|
+
getManifest: vi.fn().mockImplementation(async (id: string) => CHANNEL_MANIFESTS_FIXTURE.find((m) => m.id === id)),
|
|
23
17
|
};
|
|
24
18
|
});
|
|
25
19
|
|
|
@@ -58,12 +52,7 @@ describe("channel-manifests", () => {
|
|
|
58
52
|
const { getManifest } = await import("@/lib/channel-manifests");
|
|
59
53
|
const discord = await getManifest("discord");
|
|
60
54
|
expect(discord?.setup).toHaveLength(4);
|
|
61
|
-
expect(discord?.setup.map((s) => s.id)).toEqual([
|
|
62
|
-
"create-bot",
|
|
63
|
-
"paste-token",
|
|
64
|
-
"select-guild",
|
|
65
|
-
"done",
|
|
66
|
-
]);
|
|
55
|
+
expect(discord?.setup.map((s) => s.id)).toEqual(["create-bot", "paste-token", "select-guild", "done"]);
|
|
67
56
|
});
|
|
68
57
|
|
|
69
58
|
it("Telegram manifest has secret token field with paste flow", async () => {
|
|
@@ -480,9 +469,7 @@ describe("Wizard connection test API integration", () => {
|
|
|
480
469
|
});
|
|
481
470
|
|
|
482
471
|
await waitFor(() => {
|
|
483
|
-
expect(
|
|
484
|
-
screen.getByText("Could not reach the server. Check your connection."),
|
|
485
|
-
).toBeInTheDocument();
|
|
472
|
+
expect(screen.getByText("Could not reach the server. Check your connection.")).toBeInTheDocument();
|
|
486
473
|
});
|
|
487
474
|
});
|
|
488
475
|
|
|
@@ -48,10 +48,7 @@ describe("ChatPanel", () => {
|
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
it("renders message list with user and bot messages", () => {
|
|
51
|
-
const messages = [
|
|
52
|
-
msg({ role: "user", content: "Question?" }),
|
|
53
|
-
msg({ role: "bot", content: "Answer!" }),
|
|
54
|
-
];
|
|
51
|
+
const messages = [msg({ role: "user", content: "Question?" }), msg({ role: "bot", content: "Answer!" })];
|
|
55
52
|
render(<ChatPanel {...baseProps} messages={messages} />);
|
|
56
53
|
expect(screen.getByText("Question?")).toBeInTheDocument();
|
|
57
54
|
expect(screen.getByText("Answer!")).toBeInTheDocument();
|