@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
|
@@ -69,9 +69,7 @@ describe("chat-store", () => {
|
|
|
69
69
|
it("strips extra fields from valid messages", () => {
|
|
70
70
|
localStorage.setItem(
|
|
71
71
|
"platform-chat-history",
|
|
72
|
-
JSON.stringify([
|
|
73
|
-
{ id: "1", role: "user", content: "hi", timestamp: 1000, xss: "<script>" },
|
|
74
|
-
]),
|
|
72
|
+
JSON.stringify([{ id: "1", role: "user", content: "hi", timestamp: 1000, xss: "<script>" }]),
|
|
75
73
|
);
|
|
76
74
|
const result = loadChatHistory();
|
|
77
75
|
expect(result).toEqual([{ id: "1", role: "user", content: "hi", timestamp: 1000 }]);
|
|
@@ -106,9 +104,7 @@ describe("chat-store", () => {
|
|
|
106
104
|
|
|
107
105
|
it("truncates message content exceeding MAX_MESSAGE_CONTENT_LENGTH and appends ellipsis", () => {
|
|
108
106
|
const longContent = "x".repeat(MAX_MESSAGE_CONTENT_LENGTH + 1000);
|
|
109
|
-
const messages: ChatMessage[] = [
|
|
110
|
-
{ id: "1", role: "user", content: longContent, timestamp: 1000 },
|
|
111
|
-
];
|
|
107
|
+
const messages: ChatMessage[] = [{ id: "1", role: "user", content: longContent, timestamp: 1000 }];
|
|
112
108
|
saveChatHistory(messages);
|
|
113
109
|
const loaded = loadChatHistory();
|
|
114
110
|
expect(loaded).toHaveLength(1);
|
|
@@ -118,9 +114,7 @@ describe("chat-store", () => {
|
|
|
118
114
|
|
|
119
115
|
it("does not mutate the original messages array when saving", () => {
|
|
120
116
|
const longContent = "x".repeat(MAX_MESSAGE_CONTENT_LENGTH + 1000);
|
|
121
|
-
const messages: ChatMessage[] = [
|
|
122
|
-
{ id: "1", role: "user", content: longContent, timestamp: 1000 },
|
|
123
|
-
];
|
|
117
|
+
const messages: ChatMessage[] = [{ id: "1", role: "user", content: longContent, timestamp: 1000 }];
|
|
124
118
|
const originalContent = messages[0].content;
|
|
125
119
|
saveChatHistory(messages);
|
|
126
120
|
// localStorage copy is truncated; in-memory array must be unchanged
|
|
@@ -135,9 +129,7 @@ describe("chat-store", () => {
|
|
|
135
129
|
// With .slice() the last emoji would be split; with spread it must not be.
|
|
136
130
|
const emoji = "\u{1F600}"; // 😀 — 2 code units
|
|
137
131
|
const longContent = emoji.repeat(MAX_MESSAGE_CONTENT_LENGTH + 100);
|
|
138
|
-
const messages: ChatMessage[] = [
|
|
139
|
-
{ id: "1", role: "user", content: longContent, timestamp: 1000 },
|
|
140
|
-
];
|
|
132
|
+
const messages: ChatMessage[] = [{ id: "1", role: "user", content: longContent, timestamp: 1000 }];
|
|
141
133
|
saveChatHistory(messages);
|
|
142
134
|
const loaded = loadChatHistory();
|
|
143
135
|
const stored = loaded[0].content;
|
|
@@ -150,9 +142,7 @@ describe("chat-store", () => {
|
|
|
150
142
|
|
|
151
143
|
it("does not truncate content at or below the limit", () => {
|
|
152
144
|
const exactContent = "y".repeat(MAX_MESSAGE_CONTENT_LENGTH);
|
|
153
|
-
const messages: ChatMessage[] = [
|
|
154
|
-
{ id: "1", role: "user", content: exactContent, timestamp: 1000 },
|
|
155
|
-
];
|
|
145
|
+
const messages: ChatMessage[] = [{ id: "1", role: "user", content: exactContent, timestamp: 1000 }];
|
|
156
146
|
saveChatHistory(messages);
|
|
157
147
|
const loaded = loadChatHistory();
|
|
158
148
|
expect(loaded[0].content).toBe(exactContent);
|
|
@@ -109,18 +109,16 @@ vi.mock("@/lib/trpc", () => ({
|
|
|
109
109
|
}));
|
|
110
110
|
|
|
111
111
|
vi.mock("@/lib/api", () => ({
|
|
112
|
-
mapBotStatusToFleetInstance: vi.fn(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}),
|
|
123
|
-
),
|
|
112
|
+
mapBotStatusToFleetInstance: vi.fn((bot: { id: string; name: string; state: string; health: string | null }) => ({
|
|
113
|
+
id: bot.id,
|
|
114
|
+
name: bot.name,
|
|
115
|
+
status: bot.state === "running" ? "running" : "stopped",
|
|
116
|
+
health: bot.health === "healthy" ? "healthy" : "degraded",
|
|
117
|
+
uptime: bot.id === "inst-001" ? 86400 : null,
|
|
118
|
+
pluginCount: bot.id === "inst-001" ? 2 : bot.id === "inst-002" ? 1 : 3,
|
|
119
|
+
sessionCount: bot.id === "inst-001" ? 5 : 0,
|
|
120
|
+
provider: bot.id === "inst-001" ? "anthropic" : "openai",
|
|
121
|
+
})),
|
|
124
122
|
getActivityFeed: vi.fn().mockResolvedValue([
|
|
125
123
|
{
|
|
126
124
|
id: "evt-1",
|
|
@@ -26,9 +26,7 @@ const mockFetchRetentionPolicies = vi.fn();
|
|
|
26
26
|
const mockUpdateRetentionPolicy = vi.fn();
|
|
27
27
|
|
|
28
28
|
vi.mock("@/lib/admin-compliance-api", async () => {
|
|
29
|
-
const actual = await vi.importActual<typeof import("@/lib/admin-compliance-api")>(
|
|
30
|
-
"@/lib/admin-compliance-api",
|
|
31
|
-
);
|
|
29
|
+
const actual = await vi.importActual<typeof import("@/lib/admin-compliance-api")>("@/lib/admin-compliance-api");
|
|
32
30
|
return {
|
|
33
31
|
...actual,
|
|
34
32
|
fetchRetentionPolicies: (...args: unknown[]) => mockFetchRetentionPolicies(...args),
|
|
@@ -67,9 +65,8 @@ describe("updateRetentionPolicy", () => {
|
|
|
67
65
|
recordsAffected: 0,
|
|
68
66
|
});
|
|
69
67
|
|
|
70
|
-
const { updateRetentionPolicy } =
|
|
71
|
-
typeof import("@/lib/admin-compliance-api")
|
|
72
|
-
>("@/lib/admin-compliance-api");
|
|
68
|
+
const { updateRetentionPolicy } =
|
|
69
|
+
await vi.importActual<typeof import("@/lib/admin-compliance-api")>("@/lib/admin-compliance-api");
|
|
73
70
|
|
|
74
71
|
const result2 = await updateRetentionPolicy("audit_logs", {
|
|
75
72
|
retentionDays: 180,
|
|
@@ -5,12 +5,7 @@ import { ConfirmationTracker } from "@/components/billing/confirmation-tracker";
|
|
|
5
5
|
describe("ConfirmationTracker", () => {
|
|
6
6
|
it("shows confirmation progress", () => {
|
|
7
7
|
render(
|
|
8
|
-
<ConfirmationTracker
|
|
9
|
-
confirmations={8}
|
|
10
|
-
confirmationsRequired={20}
|
|
11
|
-
displayAmount="25.00 USDT"
|
|
12
|
-
credited={false}
|
|
13
|
-
/>,
|
|
8
|
+
<ConfirmationTracker confirmations={8} confirmationsRequired={20} displayAmount="25.00 USDT" credited={false} />,
|
|
14
9
|
);
|
|
15
10
|
expect(screen.getByText(/8/)).toBeInTheDocument();
|
|
16
11
|
expect(screen.getByText(/20/)).toBeInTheDocument();
|
|
@@ -19,24 +14,14 @@ describe("ConfirmationTracker", () => {
|
|
|
19
14
|
|
|
20
15
|
it("shows credited state", () => {
|
|
21
16
|
render(
|
|
22
|
-
<ConfirmationTracker
|
|
23
|
-
confirmations={20}
|
|
24
|
-
confirmationsRequired={20}
|
|
25
|
-
displayAmount="25.00 USDT"
|
|
26
|
-
credited={true}
|
|
27
|
-
/>,
|
|
17
|
+
<ConfirmationTracker confirmations={20} confirmationsRequired={20} displayAmount="25.00 USDT" credited={true} />,
|
|
28
18
|
);
|
|
29
19
|
expect(screen.getByText(/credits applied/i)).toBeInTheDocument();
|
|
30
20
|
});
|
|
31
21
|
|
|
32
22
|
it("renders progress bar", () => {
|
|
33
23
|
render(
|
|
34
|
-
<ConfirmationTracker
|
|
35
|
-
confirmations={10}
|
|
36
|
-
confirmationsRequired={20}
|
|
37
|
-
displayAmount="25.00 USDT"
|
|
38
|
-
credited={false}
|
|
39
|
-
/>,
|
|
24
|
+
<ConfirmationTracker confirmations={10} confirmationsRequired={20} displayAmount="25.00 USDT" credited={false} />,
|
|
40
25
|
);
|
|
41
26
|
const bar = screen.getByRole("progressbar");
|
|
42
27
|
expect(bar).toBeInTheDocument();
|
|
@@ -18,9 +18,7 @@ vi.mock("@/lib/trpc", () => ({
|
|
|
18
18
|
|
|
19
19
|
vi.mock("framer-motion", () => ({
|
|
20
20
|
motion: {
|
|
21
|
-
div: ({ children, ...props }: React.PropsWithChildren<Record<string, unknown>>) =>
|
|
22
|
-
<div {...props}>{children}</div>
|
|
23
|
-
),
|
|
21
|
+
div: ({ children, ...props }: React.PropsWithChildren<Record<string, unknown>>) => <div {...props}>{children}</div>,
|
|
24
22
|
},
|
|
25
23
|
}));
|
|
26
24
|
|
|
@@ -53,9 +53,7 @@ describe("CreateInstanceClient", () => {
|
|
|
53
53
|
|
|
54
54
|
it("renders the create form heading", async () => {
|
|
55
55
|
render(<CreateInstanceClient />);
|
|
56
|
-
await waitFor(() =>
|
|
57
|
-
expect(screen.getByRole("heading", { name: "Create Instance" })).toBeInTheDocument(),
|
|
58
|
-
);
|
|
56
|
+
await waitFor(() => expect(screen.getByRole("heading", { name: "Create Instance" })).toBeInTheDocument());
|
|
59
57
|
});
|
|
60
58
|
|
|
61
59
|
it("renders preset cards", async () => {
|
|
@@ -49,9 +49,7 @@ describe("CreditBalance", () => {
|
|
|
49
49
|
});
|
|
50
50
|
|
|
51
51
|
it("applies destructive color when balance <= 2", async () => {
|
|
52
|
-
const { container } = render(
|
|
53
|
-
<CreditBalance data={{ balance: 1.5, dailyBurn: 1.5, runway: 1 }} />,
|
|
54
|
-
);
|
|
52
|
+
const { container } = render(<CreditBalance data={{ balance: 1.5, dailyBurn: 1.5, runway: 1 }} />);
|
|
55
53
|
await waitFor(() => {
|
|
56
54
|
const balanceEl = container.querySelector(".text-4xl");
|
|
57
55
|
expect(balanceEl?.className).toContain("text-destructive");
|
|
@@ -59,9 +57,7 @@ describe("CreditBalance", () => {
|
|
|
59
57
|
});
|
|
60
58
|
|
|
61
59
|
it("applies destructive color when runway <= 1", async () => {
|
|
62
|
-
const { container } = render(
|
|
63
|
-
<CreditBalance data={{ balance: 50, dailyBurn: 50, runway: 1 }} />,
|
|
64
|
-
);
|
|
60
|
+
const { container } = render(<CreditBalance data={{ balance: 50, dailyBurn: 50, runway: 1 }} />);
|
|
65
61
|
await waitFor(() => {
|
|
66
62
|
const balanceEl = container.querySelector(".text-4xl");
|
|
67
63
|
expect(balanceEl?.className).toContain("text-destructive");
|
|
@@ -77,9 +73,7 @@ describe("CreditBalance", () => {
|
|
|
77
73
|
});
|
|
78
74
|
|
|
79
75
|
it("applies amber color when runway <= 7", async () => {
|
|
80
|
-
const { container } = render(
|
|
81
|
-
<CreditBalance data={{ balance: 50, dailyBurn: 10, runway: 5 }} />,
|
|
82
|
-
);
|
|
76
|
+
const { container } = render(<CreditBalance data={{ balance: 50, dailyBurn: 10, runway: 5 }} />);
|
|
83
77
|
await waitFor(() => {
|
|
84
78
|
const balanceEl = container.querySelector(".text-4xl");
|
|
85
79
|
expect(balanceEl?.className).toContain("text-amber-500");
|
|
@@ -87,9 +81,7 @@ describe("CreditBalance", () => {
|
|
|
87
81
|
});
|
|
88
82
|
|
|
89
83
|
it("applies emerald color for healthy balance", async () => {
|
|
90
|
-
const { container } = render(
|
|
91
|
-
<CreditBalance data={{ balance: 100, dailyBurn: 5, runway: 20 }} />,
|
|
92
|
-
);
|
|
84
|
+
const { container } = render(<CreditBalance data={{ balance: 100, dailyBurn: 5, runway: 20 }} />);
|
|
93
85
|
await waitFor(() => {
|
|
94
86
|
const balanceEl = container.querySelector(".text-4xl");
|
|
95
87
|
expect(balanceEl?.className).toContain("text-emerald-500");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { render, screen
|
|
2
|
-
import userEvent from "@testing-library/user-event";
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
3
2
|
import { describe, expect, it, vi } from "vitest";
|
|
4
3
|
import type { CreditBalance, CreditHistoryResponse } from "@/lib/api";
|
|
4
|
+
import { trpcVanillaProxy } from "./setup.js";
|
|
5
5
|
|
|
6
6
|
// Mock framer-motion to prevent animation/rAF issues in JSDOM.
|
|
7
7
|
vi.mock("framer-motion", () => {
|
|
@@ -47,6 +47,17 @@ vi.mock("@/lib/org-api", () => ({
|
|
|
47
47
|
getOrganization: vi.fn().mockRejectedValue(new Error("no org")),
|
|
48
48
|
}));
|
|
49
49
|
|
|
50
|
+
// Mock UnifiedCheckout — uses useQueryClient() which requires QueryClientProvider.
|
|
51
|
+
// The credits page tests focus on balance display and layout wiring.
|
|
52
|
+
vi.mock("@/components/billing/unified-checkout", () => ({
|
|
53
|
+
UnifiedCheckout: () => <div data-testid="unified-checkout">UnifiedCheckout</div>,
|
|
54
|
+
}));
|
|
55
|
+
|
|
56
|
+
// Mock TransactionHistory — complex component with its own data fetching.
|
|
57
|
+
vi.mock("@/components/billing/transaction-history", () => ({
|
|
58
|
+
TransactionHistory: () => <div data-testid="transaction-history">TransactionHistory</div>,
|
|
59
|
+
}));
|
|
60
|
+
|
|
50
61
|
// Mock next/navigation
|
|
51
62
|
vi.mock("next/navigation", () => ({
|
|
52
63
|
useRouter: () => ({ push: vi.fn() }),
|
|
@@ -121,8 +132,17 @@ vi.mock("@/lib/trpc", () => ({
|
|
|
121
132
|
refetch: vi.fn(),
|
|
122
133
|
}),
|
|
123
134
|
},
|
|
135
|
+
creditsDailySummary: {
|
|
136
|
+
useQuery: vi.fn().mockReturnValue({
|
|
137
|
+
data: { rows: [] },
|
|
138
|
+
isLoading: false,
|
|
139
|
+
error: null,
|
|
140
|
+
refetch: vi.fn(),
|
|
141
|
+
}),
|
|
142
|
+
},
|
|
124
143
|
},
|
|
125
144
|
},
|
|
145
|
+
trpcVanilla: trpcVanillaProxy,
|
|
126
146
|
TRPCProvider: ({ children }: { children?: unknown }) => children,
|
|
127
147
|
}));
|
|
128
148
|
|
|
@@ -148,9 +168,7 @@ vi.mock("@/lib/api", async (importOriginal) => {
|
|
|
148
168
|
bonusPercent: 10,
|
|
149
169
|
},
|
|
150
170
|
]),
|
|
151
|
-
createCreditCheckout: vi
|
|
152
|
-
.fn()
|
|
153
|
-
.mockResolvedValue({ checkoutUrl: "https://checkout.stripe.com/test" }),
|
|
171
|
+
createCreditCheckout: vi.fn().mockResolvedValue({ checkoutUrl: "https://checkout.stripe.com/test" }),
|
|
154
172
|
getAutoTopupSettings: vi.fn().mockResolvedValue({
|
|
155
173
|
usageBased: { enabled: false, thresholdCents: 500, topupAmountCents: 2000 },
|
|
156
174
|
scheduled: { enabled: false, amountCents: 2000, interval: "weekly", nextChargeDate: null },
|
|
@@ -185,93 +203,25 @@ describe("Credits page", () => {
|
|
|
185
203
|
expect(screen.getByText("~37 days")).toBeInTheDocument();
|
|
186
204
|
});
|
|
187
205
|
|
|
188
|
-
it("renders
|
|
189
|
-
const { default: CreditsPage } = await import("../app/(dashboard)/billing/credits/page");
|
|
190
|
-
render(<CreditsPage />);
|
|
191
|
-
|
|
192
|
-
const buyCreditsHeading = await screen.findByText("Buy Credits");
|
|
193
|
-
const buyCreditsPanel = buyCreditsHeading.closest('[data-slot="card"]') as HTMLElement;
|
|
194
|
-
// Note: $5, $10, $50 appear in both BuyCreditsPanel and AutoTopupCard dropdowns
|
|
195
|
-
expect((await screen.findAllByText("$5")).length).toBeGreaterThanOrEqual(1);
|
|
196
|
-
expect(screen.getAllByText("$10").length).toBeGreaterThanOrEqual(1);
|
|
197
|
-
expect(within(buyCreditsPanel).getByText("$25")).toBeInTheDocument();
|
|
198
|
-
expect(screen.getAllByText("$50").length).toBeGreaterThanOrEqual(1);
|
|
199
|
-
expect(screen.getAllByText("$100").length).toBeGreaterThanOrEqual(1);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
it("renders bonus badges on higher tiers", async () => {
|
|
203
|
-
const { default: CreditsPage } = await import("../app/(dashboard)/billing/credits/page");
|
|
204
|
-
render(<CreditsPage />);
|
|
205
|
-
|
|
206
|
-
expect(await screen.findByText("+2%")).toBeInTheDocument();
|
|
207
|
-
expect(screen.getByText("+5%")).toBeInTheDocument();
|
|
208
|
-
expect(screen.getByText("+10%")).toBeInTheDocument();
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it("renders transaction history", async () => {
|
|
212
|
-
const { default: CreditsPage } = await import("../app/(dashboard)/billing/credits/page");
|
|
213
|
-
render(<CreditsPage />);
|
|
214
|
-
|
|
215
|
-
expect(await screen.findByText("Transaction History")).toBeInTheDocument();
|
|
216
|
-
// "Signup credit" appears in both the description and the type badge
|
|
217
|
-
expect((await screen.findAllByText("Signup credit")).length).toBeGreaterThanOrEqual(1);
|
|
218
|
-
expect(screen.getByText("Bot runtime (platform-1)")).toBeInTheDocument();
|
|
219
|
-
expect(screen.getByText("Credit purchase")).toBeInTheDocument();
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it("renders positive and negative amounts with correct coloring", async () => {
|
|
206
|
+
it("renders unified checkout component", async () => {
|
|
223
207
|
const { default: CreditsPage } = await import("../app/(dashboard)/billing/credits/page");
|
|
224
208
|
render(<CreditsPage />);
|
|
225
209
|
|
|
226
|
-
|
|
227
|
-
expect(positiveAmount).toHaveClass("text-emerald-500");
|
|
228
|
-
|
|
229
|
-
const negativeAmount = screen.getByText("-$0.17");
|
|
230
|
-
expect(negativeAmount).toHaveClass("text-red-500");
|
|
210
|
+
expect(await screen.findByTestId("unified-checkout")).toBeInTheDocument();
|
|
231
211
|
});
|
|
232
212
|
|
|
233
|
-
it("renders
|
|
213
|
+
it("renders transaction history component", async () => {
|
|
234
214
|
const { default: CreditsPage } = await import("../app/(dashboard)/billing/credits/page");
|
|
235
215
|
render(<CreditsPage />);
|
|
236
216
|
|
|
237
|
-
expect(
|
|
238
|
-
await screen.findByRole("button", { name: "Load more" }, { timeout: 5000 }),
|
|
239
|
-
).toBeInTheDocument();
|
|
217
|
+
expect(await screen.findByTestId("transaction-history")).toBeInTheDocument();
|
|
240
218
|
});
|
|
241
219
|
|
|
242
|
-
it("
|
|
243
|
-
const user = userEvent.setup();
|
|
220
|
+
it("renders page description", async () => {
|
|
244
221
|
const { default: CreditsPage } = await import("../app/(dashboard)/billing/credits/page");
|
|
245
222
|
render(<CreditsPage />);
|
|
246
223
|
|
|
247
|
-
|
|
248
|
-
await user.click(loadMoreBtn);
|
|
249
|
-
|
|
250
|
-
expect(await screen.findByText("Bot runtime (platform-2)")).toBeInTheDocument();
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
it("buy credits button is disabled without selection", async () => {
|
|
254
|
-
const { default: CreditsPage } = await import("../app/(dashboard)/billing/credits/page");
|
|
255
|
-
render(<CreditsPage />);
|
|
256
|
-
|
|
257
|
-
const buyBtn = await screen.findByRole("button", { name: "Buy credits" });
|
|
258
|
-
expect(buyBtn).toBeDisabled();
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it("enables buy button after selecting a tier", async () => {
|
|
262
|
-
const user = userEvent.setup();
|
|
263
|
-
const { default: CreditsPage } = await import("../app/(dashboard)/billing/credits/page");
|
|
264
|
-
render(<CreditsPage />);
|
|
265
|
-
|
|
266
|
-
// Wait for tiers to load, then scope to the Buy Credits card to avoid
|
|
267
|
-
// matching the same dollar amounts in the BuyCryptoCreditPanel
|
|
268
|
-
const buyCreditsHeading = await screen.findByText("Buy Credits");
|
|
269
|
-
const buyCreditsPanel = buyCreditsHeading.closest('[data-slot="card"]') as HTMLElement;
|
|
270
|
-
const tier10 = await within(buyCreditsPanel).findByText("$10");
|
|
271
|
-
await user.click(tier10);
|
|
272
|
-
|
|
273
|
-
const buyBtn = screen.getByRole("button", { name: "Buy credits" });
|
|
274
|
-
expect(buyBtn).not.toBeDisabled();
|
|
224
|
+
expect(await screen.findByText("Purchase and manage your credits")).toBeInTheDocument();
|
|
275
225
|
});
|
|
276
226
|
});
|
|
277
227
|
|
|
@@ -359,8 +309,8 @@ describe("LowBalanceBanner", () => {
|
|
|
359
309
|
});
|
|
360
310
|
});
|
|
361
311
|
|
|
362
|
-
describe("Billing layout with Credits
|
|
363
|
-
it("renders
|
|
312
|
+
describe("Billing layout with Credits content", () => {
|
|
313
|
+
it("renders child content inside billing layout", async () => {
|
|
364
314
|
const { default: BillingLayout } = await import("../app/(dashboard)/billing/layout");
|
|
365
315
|
render(
|
|
366
316
|
<BillingLayout>
|
|
@@ -368,9 +318,6 @@ describe("Billing layout with Credits nav", () => {
|
|
|
368
318
|
</BillingLayout>,
|
|
369
319
|
);
|
|
370
320
|
|
|
371
|
-
expect(screen.getByText("
|
|
372
|
-
expect(screen.getByText("Your Plan")).toBeInTheDocument();
|
|
373
|
-
expect(screen.getByText("Usage")).toBeInTheDocument();
|
|
374
|
-
expect(screen.getByText("Payment")).toBeInTheDocument();
|
|
321
|
+
expect(screen.getByText("child content")).toBeInTheDocument();
|
|
375
322
|
});
|
|
376
323
|
});
|
|
@@ -18,12 +18,8 @@ vi.mock("better-auth/react", () => ({
|
|
|
18
18
|
|
|
19
19
|
vi.mock("framer-motion", () => ({
|
|
20
20
|
motion: {
|
|
21
|
-
div: ({ children, ...props }: React.PropsWithChildren<Record<string, unknown>>) =>
|
|
22
|
-
|
|
23
|
-
),
|
|
24
|
-
p: ({ children, ...props }: React.PropsWithChildren<Record<string, unknown>>) => (
|
|
25
|
-
<p {...props}>{children}</p>
|
|
26
|
-
),
|
|
21
|
+
div: ({ children, ...props }: React.PropsWithChildren<Record<string, unknown>>) => <div {...props}>{children}</div>,
|
|
22
|
+
p: ({ children, ...props }: React.PropsWithChildren<Record<string, unknown>>) => <p {...props}>{children}</p>,
|
|
27
23
|
},
|
|
28
24
|
}));
|
|
29
25
|
|
|
@@ -24,7 +24,6 @@ const boundaries = [
|
|
|
24
24
|
let consoleErrorSpy: ReturnType<typeof vi.spyOn>;
|
|
25
25
|
|
|
26
26
|
beforeEach(() => {
|
|
27
|
-
// biome-ignore lint/suspicious/noEmptyBlockStatements: intentional suppression of console.error in tests
|
|
28
27
|
consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
29
28
|
});
|
|
30
29
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { trpcVanillaProxy } from "./setup.js";
|
|
2
3
|
|
|
3
4
|
// Must mock before importing
|
|
4
5
|
vi.mock("@/lib/api-config", () => ({
|
|
@@ -8,7 +9,7 @@ vi.mock("@/lib/api-config", () => ({
|
|
|
8
9
|
|
|
9
10
|
// Mock trpc and fetch-utils so api.ts can import without issues
|
|
10
11
|
vi.mock("@/lib/trpc", () => ({
|
|
11
|
-
trpcVanilla:
|
|
12
|
+
trpcVanilla: trpcVanillaProxy,
|
|
12
13
|
}));
|
|
13
14
|
|
|
14
15
|
vi.mock("@/lib/fetch-utils", () => ({
|
|
@@ -61,9 +61,7 @@ describe("FieldOAuth", () => {
|
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
it("shows error prop message", () => {
|
|
64
|
-
render(
|
|
65
|
-
<FieldOAuth field={slackOAuthField} value="" onChange={vi.fn()} error="Token is required" />,
|
|
66
|
-
);
|
|
64
|
+
render(<FieldOAuth field={slackOAuthField} value="" onChange={vi.fn()} error="Token is required" />);
|
|
67
65
|
expect(screen.getByText("Token is required")).toBeInTheDocument();
|
|
68
66
|
});
|
|
69
67
|
|
|
@@ -90,9 +88,7 @@ describe("FieldOAuth", () => {
|
|
|
90
88
|
fireEvent.click(screen.getByRole("button", { name: "Authorize" }));
|
|
91
89
|
|
|
92
90
|
await waitFor(() => {
|
|
93
|
-
expect(
|
|
94
|
-
screen.getByText("Popup blocked. Please allow popups for this site and try again."),
|
|
95
|
-
).toBeInTheDocument();
|
|
91
|
+
expect(screen.getByText("Popup blocked. Please allow popups for this site and try again.")).toBeInTheDocument();
|
|
96
92
|
});
|
|
97
93
|
expect(screen.getByRole("button", { name: "Retry" })).toBeInTheDocument();
|
|
98
94
|
});
|
|
@@ -67,9 +67,7 @@ const MARKETPLACE_TEST_PLUGINS = [
|
|
|
67
67
|
],
|
|
68
68
|
connectionTest: { label: "Test Bot Connection", endpoint: "/api/channels/discord/test" },
|
|
69
69
|
installCount: 12400,
|
|
70
|
-
changelog: [
|
|
71
|
-
{ version: "3.2.0", date: "2026-02-10", notes: "Added thread support and slash commands." },
|
|
72
|
-
],
|
|
70
|
+
changelog: [{ version: "3.2.0", date: "2026-02-10", notes: "Added thread support and slash commands." }],
|
|
73
71
|
marketplaceTab: "channel",
|
|
74
72
|
},
|
|
75
73
|
{
|
|
@@ -13,10 +13,8 @@ const data = require("./mock-manifests-data") as {
|
|
|
13
13
|
CHANNEL_MANIFESTS_FIXTURE: ChannelManifest[];
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
export const MARKETPLACE_TEST_PLUGINS: Array<Record<string, unknown>> =
|
|
17
|
-
|
|
18
|
-
export const INSTALL_FLOW_TEST_PLUGINS: Array<Record<string, unknown>> =
|
|
19
|
-
data.INSTALL_FLOW_TEST_PLUGINS;
|
|
16
|
+
export const MARKETPLACE_TEST_PLUGINS: Array<Record<string, unknown>> = data.MARKETPLACE_TEST_PLUGINS;
|
|
17
|
+
export const INSTALL_FLOW_TEST_PLUGINS: Array<Record<string, unknown>> = data.INSTALL_FLOW_TEST_PLUGINS;
|
|
20
18
|
export const findManifest: (id: string) => Record<string, unknown> = data.findManifest;
|
|
21
19
|
export const DISCORD_MANIFEST: ChannelManifest = data.DISCORD_MANIFEST;
|
|
22
20
|
export const TELEGRAM_MANIFEST: ChannelManifest = data.TELEGRAM_MANIFEST;
|
|
@@ -32,14 +32,7 @@ vi.mock("@/lib/trpc", () => ({
|
|
|
32
32
|
|
|
33
33
|
vi.mock("@/lib/api", () => ({
|
|
34
34
|
mapBotStatusToFleetInstance: vi.fn(
|
|
35
|
-
(bot: {
|
|
36
|
-
id: string;
|
|
37
|
-
name: string;
|
|
38
|
-
state: string;
|
|
39
|
-
health: string | null;
|
|
40
|
-
uptime: string | null;
|
|
41
|
-
stats: null;
|
|
42
|
-
}) => ({
|
|
35
|
+
(bot: { id: string; name: string; state: string; health: string | null; uptime: string | null; stats: null }) => ({
|
|
43
36
|
id: bot.id,
|
|
44
37
|
name: bot.name,
|
|
45
38
|
status: bot.state === "running" ? "running" : "stopped",
|
|
@@ -32,14 +32,7 @@ vi.mock("@/lib/trpc", () => ({
|
|
|
32
32
|
|
|
33
33
|
vi.mock("@/lib/api", () => ({
|
|
34
34
|
mapBotStatusToFleetInstance: vi.fn(
|
|
35
|
-
(bot: {
|
|
36
|
-
id: string;
|
|
37
|
-
name: string;
|
|
38
|
-
state: string;
|
|
39
|
-
health: string | null;
|
|
40
|
-
uptime: string | null;
|
|
41
|
-
stats: null;
|
|
42
|
-
}) => ({
|
|
35
|
+
(bot: { id: string; name: string; state: string; health: string | null; uptime: string | null; stats: null }) => ({
|
|
43
36
|
id: bot.id,
|
|
44
37
|
name: bot.name,
|
|
45
38
|
status: bot.state === "running" ? "running" : "stopped",
|
|
@@ -6,9 +6,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
6
6
|
// ---- Mock framer-motion ----
|
|
7
7
|
vi.mock("framer-motion", () => ({
|
|
8
8
|
motion: {
|
|
9
|
-
div: ({ children, ...props }: HTMLAttributes<HTMLDivElement>) =>
|
|
10
|
-
<div {...props}>{children}</div>
|
|
11
|
-
),
|
|
9
|
+
div: ({ children, ...props }: HTMLAttributes<HTMLDivElement>) => <div {...props}>{children}</div>,
|
|
12
10
|
},
|
|
13
11
|
}));
|
|
14
12
|
|
|
@@ -225,9 +223,7 @@ describe("GpuDashboard", () => {
|
|
|
225
223
|
await userEvent.click(screen.getByRole("button", { name: /^Provision$/ }));
|
|
226
224
|
|
|
227
225
|
await waitFor(() => {
|
|
228
|
-
expect(mockProvisionGpuNode).toHaveBeenCalledWith(
|
|
229
|
-
expect.objectContaining({ name: "fresh-gpu" }),
|
|
230
|
-
);
|
|
226
|
+
expect(mockProvisionGpuNode).toHaveBeenCalledWith(expect.objectContaining({ name: "fresh-gpu" }));
|
|
231
227
|
});
|
|
232
228
|
await waitFor(() => {
|
|
233
229
|
expect(mockToast.success).toHaveBeenCalledWith(expect.stringContaining("fresh-gpu"));
|
|
@@ -45,9 +45,7 @@ vi.mock("@/lib/api", () => ({
|
|
|
45
45
|
pullImageUpdate: vi.fn().mockResolvedValue(undefined),
|
|
46
46
|
getInstanceLogs: vi
|
|
47
47
|
.fn()
|
|
48
|
-
.mockResolvedValue([
|
|
49
|
-
{ id: "log-1", level: "info", message: "Bot started", timestamp: "2026-02-14T10:00:00Z" },
|
|
50
|
-
]),
|
|
48
|
+
.mockResolvedValue([{ id: "log-1", level: "info", message: "Bot started", timestamp: "2026-02-14T10:00:00Z" }]),
|
|
51
49
|
listSnapshots: vi.fn().mockResolvedValue([
|
|
52
50
|
{
|
|
53
51
|
id: "snap-001",
|
|
@@ -336,9 +334,7 @@ describe("InstanceDetailClient", () => {
|
|
|
336
334
|
await user.click(screen.getByText("Pull Update"));
|
|
337
335
|
|
|
338
336
|
await waitFor(() => {
|
|
339
|
-
expect(
|
|
340
|
-
screen.getByText("This will pull the latest image and restart the bot. Continue?"),
|
|
341
|
-
).toBeInTheDocument();
|
|
337
|
+
expect(screen.getByText("This will pull the latest image and restart the bot. Continue?")).toBeInTheDocument();
|
|
342
338
|
});
|
|
343
339
|
|
|
344
340
|
await user.click(screen.getByRole("button", { name: "Continue" }));
|
|
@@ -359,9 +355,7 @@ describe("InstanceDetailClient", () => {
|
|
|
359
355
|
await user.click(screen.getByText("Pull Update"));
|
|
360
356
|
|
|
361
357
|
await waitFor(() => {
|
|
362
|
-
expect(
|
|
363
|
-
screen.getByText("This will pull the latest image and restart the bot. Continue?"),
|
|
364
|
-
).toBeInTheDocument();
|
|
358
|
+
expect(screen.getByText("This will pull the latest image and restart the bot. Continue?")).toBeInTheDocument();
|
|
365
359
|
});
|
|
366
360
|
|
|
367
361
|
await user.click(screen.getByRole("button", { name: "Cancel" }));
|
|
@@ -86,11 +86,7 @@ vi.mock("@/lib/api", () => ({
|
|
|
86
86
|
parsePluginsFromEnv: vi.fn((env?: Record<string, string>) => {
|
|
87
87
|
if (!env) return [];
|
|
88
88
|
const ids = new Set<string>();
|
|
89
|
-
for (const key of [
|
|
90
|
-
"PLATFORM_PLUGINS_OTHER",
|
|
91
|
-
"PLATFORM_PLUGINS_VOICE",
|
|
92
|
-
"PLATFORM_PLUGINS_PROVIDERS",
|
|
93
|
-
]) {
|
|
89
|
+
for (const key of ["PLATFORM_PLUGINS_OTHER", "PLATFORM_PLUGINS_VOICE", "PLATFORM_PLUGINS_PROVIDERS"]) {
|
|
94
90
|
const raw = env[key];
|
|
95
91
|
if (raw) {
|
|
96
92
|
for (const id of raw
|