@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.
Files changed (353) hide show
  1. package/next.config.ts +1 -2
  2. package/package.json +17 -17
  3. package/src/__tests__/account-switcher.test.tsx +21 -20
  4. package/src/__tests__/activity-page.test.tsx +2 -6
  5. package/src/__tests__/add-payment-method-dialog.test.tsx +9 -32
  6. package/src/__tests__/admin-api.test.ts +1 -6
  7. package/src/__tests__/admin-gpu-api.test.ts +1 -3
  8. package/src/__tests__/admin-marketplace-api.test.ts +1 -4
  9. package/src/__tests__/admin-middleware.test.ts +76 -83
  10. package/src/__tests__/affiliate-dashboard.test.tsx +3 -3
  11. package/src/__tests__/api-401-redirect.test.ts +46 -9
  12. package/src/__tests__/api-client.test.ts +3 -5
  13. package/src/__tests__/api-config.test.ts +22 -42
  14. package/src/__tests__/api-fleet-resources.test.ts +1 -2
  15. package/src/__tests__/api-fleet-trpc.test.ts +2 -8
  16. package/src/__tests__/api-null-guards.test.ts +3 -1
  17. package/src/__tests__/audit-log-table-pagination.test.tsx +2 -6
  18. package/src/__tests__/auth-password-reset.test.tsx +7 -21
  19. package/src/__tests__/auth-redirect.test.tsx +8 -2
  20. package/src/__tests__/auth.test.tsx +25 -23
  21. package/src/__tests__/auto-topup-card.test.tsx +4 -12
  22. package/src/__tests__/backups-tab.test.tsx +3 -4
  23. package/src/__tests__/billing-layout-nav-hidden.test.tsx +5 -37
  24. package/src/__tests__/billing-payment-org-invoices.test.tsx +2 -18
  25. package/src/__tests__/billing.test.tsx +8 -39
  26. package/src/__tests__/bot-settings/resources-tab.test.tsx +1 -3
  27. package/src/__tests__/bot-settings/storage-tab.test.tsx +1 -3
  28. package/src/__tests__/bot-settings/vps-upgrade-card.test.tsx +1 -3
  29. package/src/__tests__/bot-settings-restart.test.tsx +1 -3
  30. package/src/__tests__/bot-settings.test.tsx +2 -6
  31. package/src/__tests__/brand.test.ts +6 -26
  32. package/src/__tests__/buy-credits-panel.test.tsx +1 -3
  33. package/src/__tests__/buy-crypto-credits-panel.test.tsx +101 -119
  34. package/src/__tests__/capability-conflicts.test.ts +2 -8
  35. package/src/__tests__/capability-resolver.test.tsx +2 -12
  36. package/src/__tests__/channel-wizard.test.tsx +4 -17
  37. package/src/__tests__/chat/chat-panel.test.tsx +1 -4
  38. package/src/__tests__/chat-store.test.ts +5 -15
  39. package/src/__tests__/command-center.test.tsx +10 -12
  40. package/src/__tests__/compliance-retention-edit.test.tsx +3 -6
  41. package/src/__tests__/confirmation-tracker.test.tsx +3 -18
  42. package/src/__tests__/coupon-input.test.tsx +1 -3
  43. package/src/__tests__/create-instance.test.tsx +1 -3
  44. package/src/__tests__/credit-balance.test.tsx +4 -12
  45. package/src/__tests__/credits.test.tsx +32 -85
  46. package/src/__tests__/email-verification-banner.test.tsx +2 -6
  47. package/src/__tests__/error-boundaries.test.tsx +0 -1
  48. package/src/__tests__/fetch-pricing.test.ts +2 -1
  49. package/src/__tests__/field-oauth.test.tsx +2 -6
  50. package/src/__tests__/fixtures/mock-manifests-data.js +1 -3
  51. package/src/__tests__/fixtures/mock-manifests.ts +2 -4
  52. package/src/__tests__/fleet-health-timestamp.test.tsx +1 -8
  53. package/src/__tests__/fleet-health-update.test.tsx +1 -8
  54. package/src/__tests__/gpu-dashboard.test.tsx +2 -6
  55. package/src/__tests__/instance-detail.test.tsx +3 -9
  56. package/src/__tests__/instance-list.test.tsx +1 -5
  57. package/src/__tests__/layout-snapshots.test.tsx +64 -11
  58. package/src/__tests__/marketplace-admin.test.tsx +2 -6
  59. package/src/__tests__/marketplace.test.tsx +11 -35
  60. package/src/__tests__/merge-api-rates.test.ts +1 -6
  61. package/src/__tests__/middleware.test.ts +32 -219
  62. package/src/__tests__/next-config-headers.test.ts +1 -3
  63. package/src/__tests__/notifications.test.tsx +4 -11
  64. package/src/__tests__/oauth-buttons.test.tsx +36 -59
  65. package/src/__tests__/oauth-error-mapping.test.tsx +2 -6
  66. package/src/__tests__/observability.test.tsx +23 -36
  67. package/src/__tests__/onboarding-page.test.tsx +4 -6
  68. package/src/__tests__/org-billing-api.test.tsx +1 -6
  69. package/src/__tests__/plugin-install-flow.test.tsx +28 -58
  70. package/src/__tests__/plugin-registry.test.tsx +3 -11
  71. package/src/__tests__/plugin-tool-sync.test.ts +1 -3
  72. package/src/__tests__/plugins-catalog-error.test.tsx +2 -6
  73. package/src/__tests__/plugins-toggle-race.test.tsx +3 -5
  74. package/src/__tests__/portfolio-chart.test.tsx +2 -6
  75. package/src/__tests__/promotion-form.test.tsx +2 -6
  76. package/src/__tests__/promotions-list.test.tsx +1 -3
  77. package/src/__tests__/provider-key-api.test.ts +2 -1
  78. package/src/__tests__/resend-verification-button.test.tsx +8 -24
  79. package/src/__tests__/secrets-audit-pagination.test.tsx +1 -3
  80. package/src/__tests__/settings.test.tsx +11 -21
  81. package/src/__tests__/setup-checklist.test.tsx +3 -9
  82. package/src/__tests__/setup.ts +25 -6
  83. package/src/__tests__/snapshot-api.test.ts +2 -1
  84. package/src/__tests__/step-superpowers.test.tsx +1 -3
  85. package/src/__tests__/tenant-context.test.tsx +1 -6
  86. package/src/__tests__/tenant-keys-api.test.ts +3 -4
  87. package/src/__tests__/tenant-table-pagination.test.tsx +2 -6
  88. package/src/__tests__/terminal-log-cleanup.test.tsx +0 -1
  89. package/src/__tests__/transaction-history.test.tsx +190 -238
  90. package/src/__tests__/trpc-types.test.ts +2 -6
  91. package/src/__tests__/use-chat.test.ts +1 -3
  92. package/src/__tests__/use-plugin-setup-chat-stale-closure.test.ts +1 -4
  93. package/src/__tests__/use-sidecar-bridge.test.tsx +105 -0
  94. package/src/__tests__/use-webmcp.test.ts +1 -3
  95. package/src/__tests__/validate-elevenlabs-key.test.ts +2 -1
  96. package/src/__tests__/verify-page.test.tsx +4 -13
  97. package/src/__tests__/verify-redirect.test.tsx +2 -6
  98. package/src/app/(auth)/error.tsx +1 -7
  99. package/src/app/(auth)/forgot-password/page.tsx +4 -18
  100. package/src/app/(auth)/login/page.tsx +5 -22
  101. package/src/app/(auth)/reset-password/page.tsx +2 -12
  102. package/src/app/(auth)/signup/page.tsx +10 -44
  103. package/src/app/(auth)/verify/page.tsx +47 -0
  104. package/src/app/(dashboard)/billing/credits/page.tsx +14 -67
  105. package/src/app/(dashboard)/billing/error.tsx +2 -10
  106. package/src/app/(dashboard)/billing/layout.tsx +12 -62
  107. package/src/app/(dashboard)/billing/payment/page.tsx +17 -68
  108. package/src/app/(dashboard)/billing/plans/page.tsx +3 -9
  109. package/src/app/(dashboard)/billing/usage/hosted/page.tsx +8 -25
  110. package/src/app/(dashboard)/billing/usage/page.tsx +63 -103
  111. package/src/app/(dashboard)/changesets/[id]/changeset-detail-client.tsx +9 -27
  112. package/src/app/(dashboard)/changesets/[id]/error.tsx +2 -6
  113. package/src/app/(dashboard)/changesets/error.tsx +1 -7
  114. package/src/app/(dashboard)/chat/page.tsx +2 -6
  115. package/src/app/(dashboard)/dashboard/network/page.tsx +5 -19
  116. package/src/app/(dashboard)/error.tsx +1 -7
  117. package/src/app/(dashboard)/layout.tsx +15 -36
  118. package/src/app/(dashboard)/marketplace/[plugin]/page.tsx +14 -51
  119. package/src/app/(dashboard)/marketplace/error.tsx +1 -7
  120. package/src/app/(dashboard)/marketplace/page.tsx +6 -27
  121. package/src/app/(dashboard)/not-found.tsx +2 -5
  122. package/src/app/(dashboard)/onboarding/page.tsx +5 -22
  123. package/src/app/(dashboard)/settings/account/page.tsx +1 -6
  124. package/src/app/(dashboard)/settings/activity/page.tsx +8 -34
  125. package/src/app/(dashboard)/settings/api-keys/page.tsx +15 -60
  126. package/src/app/(dashboard)/settings/brain/page.tsx +9 -31
  127. package/src/app/(dashboard)/settings/error.tsx +2 -10
  128. package/src/app/(dashboard)/settings/notifications/page.tsx +2 -6
  129. package/src/app/(dashboard)/settings/org/page.tsx +13 -56
  130. package/src/app/(dashboard)/settings/page.tsx +1 -0
  131. package/src/app/(dashboard)/settings/profile/page.tsx +126 -73
  132. package/src/app/(dashboard)/settings/providers/page.tsx +21 -78
  133. package/src/app/(dashboard)/settings/secrets/page.tsx +13 -58
  134. package/src/app/(dashboard)/settings/security/page.tsx +31 -111
  135. package/src/app/admin/email-templates/email-templates-client.tsx +15 -58
  136. package/src/app/admin/error.tsx +1 -7
  137. package/src/app/admin/fleet-updates/error.tsx +1 -7
  138. package/src/app/admin/fleet-updates/fleet-updates-client.tsx +10 -50
  139. package/src/app/admin/layout.tsx +4 -0
  140. package/src/app/admin/payment-methods/page.tsx +9 -38
  141. package/src/app/admin/products/error.tsx +2 -7
  142. package/src/app/admin/products/page.tsx +1 -4
  143. package/src/app/admin/promotions/[id]/page.tsx +9 -38
  144. package/src/app/admin/promotions/page.tsx +9 -36
  145. package/src/app/admin/rate-overrides/page.tsx +9 -45
  146. package/src/app/auth/callback/[provider]/page.tsx +1 -8
  147. package/src/app/auth/verify/page.tsx +9 -36
  148. package/src/app/channels/error.tsx +2 -10
  149. package/src/app/channels/layout.tsx +9 -0
  150. package/src/app/channels/page.tsx +8 -20
  151. package/src/app/channels/setup/[plugin]/page.tsx +3 -5
  152. package/src/app/error.tsx +1 -7
  153. package/src/app/fleet/error.tsx +1 -7
  154. package/src/app/fleet/layout.tsx +5 -0
  155. package/src/app/fleet/settings/page.tsx +1 -3
  156. package/src/app/global-error.tsx +2 -10
  157. package/src/app/globals.css +1 -4
  158. package/src/app/instances/[id]/instance-detail-client.tsx +51 -125
  159. package/src/app/instances/error.tsx +2 -10
  160. package/src/app/instances/instance-list-client.tsx +20 -69
  161. package/src/app/instances/layout.tsx +9 -0
  162. package/src/app/instances/new/create-instance-client.tsx +10 -31
  163. package/src/app/layout.tsx +2 -10
  164. package/src/app/not-found.tsx +1 -3
  165. package/src/app/page.tsx +1 -2
  166. package/src/app/plugins/error.tsx +2 -10
  167. package/src/app/plugins/layout.tsx +5 -0
  168. package/src/app/plugins/page.tsx +16 -48
  169. package/src/app/pricing/error.tsx +1 -7
  170. package/src/app/privacy/page.tsx +93 -150
  171. package/src/app/status/error.tsx +1 -7
  172. package/src/app/terms/page.tsx +89 -144
  173. package/src/components/account-switcher.tsx +25 -52
  174. package/src/components/admin/accounting-dashboard.tsx +1 -3
  175. package/src/components/admin/admin-guard.tsx +1 -3
  176. package/src/components/admin/admin-nav.tsx +1 -3
  177. package/src/components/admin/affiliate-dashboard.tsx +25 -94
  178. package/src/components/admin/audit-log-table.tsx +13 -49
  179. package/src/components/admin/billing-health-dashboard.tsx +7 -25
  180. package/src/components/admin/bulk-actions-bar.test.tsx +1 -7
  181. package/src/components/admin/bulk-actions-bar.tsx +1 -3
  182. package/src/components/admin/bulk-export-dialog.test.tsx +1 -7
  183. package/src/components/admin/bulk-export-dialog.tsx +6 -32
  184. package/src/components/admin/bulk-grant-dialog.test.tsx +2 -6
  185. package/src/components/admin/bulk-grant-dialog.tsx +4 -15
  186. package/src/components/admin/bulk-preview-dialog.tsx +3 -12
  187. package/src/components/admin/bulk-reactivate-dialog.tsx +1 -7
  188. package/src/components/admin/bulk-select-all-banner.tsx +1 -6
  189. package/src/components/admin/bulk-suspend-dialog.tsx +5 -12
  190. package/src/components/admin/bulk-undo-toast.tsx +1 -2
  191. package/src/components/admin/compliance-dashboard.tsx +31 -101
  192. package/src/components/admin/gpu-dashboard.tsx +21 -70
  193. package/src/components/admin/grant-credits-dialog.tsx +4 -17
  194. package/src/components/admin/incident-dashboard.tsx +10 -25
  195. package/src/components/admin/inference-dashboard.tsx +14 -54
  196. package/src/components/admin/marketplace-admin.tsx +18 -60
  197. package/src/components/admin/migrations-dashboard.tsx +9 -42
  198. package/src/components/admin/onboarding-dashboard.tsx +14 -64
  199. package/src/components/admin/pool-config-dashboard.tsx +4 -10
  200. package/src/components/admin/products/fleet-form.tsx +2 -11
  201. package/src/components/admin/products/nav-editor.tsx +3 -10
  202. package/src/components/admin/promotions/promotion-form.tsx +9 -42
  203. package/src/components/admin/roles-dashboard.tsx +7 -34
  204. package/src/components/admin/suspend-dialog.tsx +4 -11
  205. package/src/components/admin/tenant-notes-panel.tsx +1 -3
  206. package/src/components/admin/tenant-row-actions.tsx +4 -20
  207. package/src/components/admin/tenant-table.tsx +12 -49
  208. package/src/components/auth/auth-redirect.tsx +11 -3
  209. package/src/components/auth/email-verification-result-banner.tsx +1 -3
  210. package/src/components/auth/resend-verification-button.tsx +2 -10
  211. package/src/components/auth/wopr-wordmark.tsx +1 -3
  212. package/src/components/billing/add-payment-method-dialog.tsx +1 -2
  213. package/src/components/billing/affiliate-dashboard.tsx +4 -16
  214. package/src/components/billing/amount-selector.tsx +1 -3
  215. package/src/components/billing/auto-topup-card.tsx +2 -11
  216. package/src/components/billing/buy-credits-panel.tsx +4 -14
  217. package/src/components/billing/byok-callout.tsx +6 -8
  218. package/src/components/billing/confirmation-tracker.tsx +4 -14
  219. package/src/components/billing/credit-balance-badge.tsx +22 -0
  220. package/src/components/billing/credit-balance.tsx +3 -9
  221. package/src/components/billing/crypto-checkout.tsx +5 -24
  222. package/src/components/billing/degraded-state-banner.tsx +1 -3
  223. package/src/components/billing/deposit-view.tsx +301 -41
  224. package/src/components/billing/dividend-banner.tsx +1 -3
  225. package/src/components/billing/dividend-eligibility.tsx +3 -12
  226. package/src/components/billing/dividend-pool-stats.tsx +6 -20
  227. package/src/components/billing/first-dividend-dialog.tsx +2 -2
  228. package/src/components/billing/org-billing-page.tsx +8 -31
  229. package/src/components/billing/payment-method-picker.tsx +2 -10
  230. package/src/components/billing/suspension-banner.tsx +2 -7
  231. package/src/components/billing/transaction-history.tsx +10 -58
  232. package/src/components/billing/unified-checkout.tsx +547 -0
  233. package/src/components/bot-settings/backups-tab.tsx +9 -33
  234. package/src/components/bot-settings/bot-settings-client.tsx +32 -134
  235. package/src/components/bot-settings/resources-tab.tsx +2 -9
  236. package/src/components/bot-settings/storage-tab.tsx +19 -48
  237. package/src/components/bot-settings/vps-info-panel.tsx +3 -11
  238. package/src/components/bot-settings/vps-upgrade-card.tsx +3 -4
  239. package/src/components/brand-hydrator.tsx +13 -0
  240. package/src/components/channel-wizard/field-interactive.tsx +1 -3
  241. package/src/components/channel-wizard/field-qr.tsx +10 -39
  242. package/src/components/channel-wizard/step-renderer.tsx +5 -28
  243. package/src/components/channel-wizard/wizard.tsx +6 -31
  244. package/src/components/chat/chat-message.tsx +1 -4
  245. package/src/components/chat/chat-panel.tsx +4 -18
  246. package/src/components/chat/chat-widget.tsx +3 -14
  247. package/src/components/dashboard/command-center.tsx +15 -61
  248. package/src/components/fleet/update-settings-card.tsx +7 -23
  249. package/src/components/instance-update-banner.tsx +130 -0
  250. package/src/components/instances/friends-tab.test.tsx +2 -9
  251. package/src/components/instances/friends-tab.tsx +18 -74
  252. package/src/components/instances/update-available-badge.tsx +2 -11
  253. package/src/components/landing/hero.tsx +3 -9
  254. package/src/components/landing/landing-page.tsx +1 -3
  255. package/src/components/landing/portfolio-chart.tsx +4 -9
  256. package/src/components/landing/story-sections.tsx +1 -3
  257. package/src/components/landing/terminal-sequence.tsx +4 -17
  258. package/src/components/marketplace/empty-state.tsx +2 -6
  259. package/src/components/marketplace/first-visit-hero.tsx +1 -3
  260. package/src/components/marketplace/install-wizard.tsx +20 -77
  261. package/src/components/marketplace/marketplace-tabs.tsx +1 -4
  262. package/src/components/marketplace/plugin-card.tsx +2 -9
  263. package/src/components/marketplace/superpower-content.tsx +1 -3
  264. package/src/components/marketplace/terminal-search.tsx +2 -8
  265. package/src/components/oauth-buttons.tsx +29 -14
  266. package/src/components/observability/fleet-health.tsx +5 -18
  267. package/src/components/observability/health-overview.tsx +7 -20
  268. package/src/components/observability/logs-viewer.tsx +8 -32
  269. package/src/components/observability/metrics-dashboard.tsx +2 -15
  270. package/src/components/onboarding/fallback-setup.tsx +6 -25
  271. package/src/components/onboarding/setup-checklist.tsx +18 -51
  272. package/src/components/onboarding/step-superpowers.tsx +1 -4
  273. package/src/components/plugin-setup/setup-chat-panel.tsx +6 -22
  274. package/src/components/pricing/dividend-calculator.tsx +6 -12
  275. package/src/components/pricing/dividend-stats.tsx +5 -17
  276. package/src/components/pricing/pricing-page.tsx +17 -36
  277. package/src/components/settings/create-org-wizard.tsx +2 -5
  278. package/src/components/sidebar.tsx +7 -42
  279. package/src/components/sidecar-frame.tsx +78 -0
  280. package/src/components/status/status-page.tsx +6 -28
  281. package/src/components/ui/alert-dialog.tsx +8 -25
  282. package/src/components/ui/badge.tsx +2 -8
  283. package/src/components/ui/banner.tsx +1 -6
  284. package/src/components/ui/card.tsx +5 -24
  285. package/src/components/ui/checkbox.tsx +1 -5
  286. package/src/components/ui/collapsible.tsx +3 -8
  287. package/src/components/ui/dialog.tsx +4 -10
  288. package/src/components/ui/dropdown-menu.tsx +9 -18
  289. package/src/components/ui/form.tsx +2 -16
  290. package/src/components/ui/popover.tsx +3 -23
  291. package/src/components/ui/progress.tsx +1 -5
  292. package/src/components/ui/radio-group.tsx +3 -15
  293. package/src/components/ui/select.tsx +4 -17
  294. package/src/components/ui/sheet.tsx +5 -19
  295. package/src/components/ui/skeleton.tsx +1 -7
  296. package/src/components/ui/table.tsx +5 -22
  297. package/src/components/ui/tabs.tsx +3 -13
  298. package/src/components/ui/tooltip.tsx +1 -1
  299. package/src/components/unified-sidebar.tsx +493 -0
  300. package/src/hooks/__tests__/use-fleet-sse.test.ts +1 -4
  301. package/src/hooks/__tests__/use-save-queue.test.ts +2 -8
  302. package/src/hooks/use-credit-balance.ts +27 -0
  303. package/src/hooks/use-my-org-role.ts +1 -3
  304. package/src/hooks/use-plugin-registry.ts +8 -14
  305. package/src/hooks/use-plugin-setup-chat.ts +2 -5
  306. package/src/hooks/use-sidecar-bridge.tsx +148 -0
  307. package/src/hooks/use-webmcp.ts +1 -4
  308. package/src/lib/__tests__/admin-api.test.ts +1 -3
  309. package/src/lib/__tests__/api-bot-crud.test.ts +8 -18
  310. package/src/lib/__tests__/api-fetch.test.ts +4 -16
  311. package/src/lib/__tests__/org-billing-api.test.ts +1 -3
  312. package/src/lib/__tests__/pricing-data.test.ts +0 -8
  313. package/src/lib/__tests__/settings-api.test.ts +1 -3
  314. package/src/lib/admin-affiliate-api.ts +2 -7
  315. package/src/lib/admin-api.ts +6 -26
  316. package/src/lib/admin-incident-api.ts +11 -19
  317. package/src/lib/admin-marketplace-api.ts +1 -5
  318. package/src/lib/api-config.test.ts +5 -50
  319. package/src/lib/api.ts +143 -122
  320. package/src/lib/auth-client.ts +1 -2
  321. package/src/lib/bot-settings-data.ts +11 -36
  322. package/src/lib/brand-config.ts +56 -115
  323. package/src/lib/brand.ts +2 -15
  324. package/src/lib/chat/use-chat.ts +2 -7
  325. package/src/lib/cost-comparison-data.test.ts +1 -3
  326. package/src/lib/cost-comparison-data.ts +1 -4
  327. package/src/lib/errors.ts +1 -4
  328. package/src/lib/fetch-utils.test.ts +26 -9
  329. package/src/lib/fetch-utils.ts +40 -11
  330. package/src/lib/logger.ts +2 -0
  331. package/src/lib/marketplace-data.ts +3 -11
  332. package/src/lib/oauth-errors.ts +2 -4
  333. package/src/lib/onboarding-data.ts +3 -11
  334. package/src/lib/org-api.ts +2 -10
  335. package/src/lib/org-billing-api.ts +5 -19
  336. package/src/lib/plugin/tool-definitions.ts +1 -2
  337. package/src/lib/require-auth.ts +57 -0
  338. package/src/lib/settings-api.ts +1 -4
  339. package/src/lib/sidecar-routes.ts +43 -0
  340. package/src/lib/trpc-server.ts +49 -0
  341. package/src/lib/trpc-types.ts +4 -6
  342. package/src/lib/trpc.tsx +12 -4
  343. package/src/lib/validate-redirect-url.ts +1 -4
  344. package/src/lib/webmcp/marketplace-onboarding-tools.ts +6 -16
  345. package/src/lib/webmcp/register.ts +1 -4
  346. package/src/lib/webmcp/tools.ts +2 -9
  347. package/src/proxy.ts +35 -212
  348. package/src/types/missing-deps.d.ts +2 -8
  349. package/tsconfig.json +1 -8
  350. package/biome.json +0 -52
  351. package/src/__tests__/__snapshots__/layout-snapshots.test.tsx.snap +0 -741
  352. package/src/__tests__/billing-byok-callout.test.tsx +0 -76
  353. 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
- (bot: { id: string; name: string; state: string; health: string | null }) => ({
114
- id: bot.id,
115
- name: bot.name,
116
- status: bot.state === "running" ? "running" : "stopped",
117
- health: bot.health === "healthy" ? "healthy" : "degraded",
118
- uptime: bot.id === "inst-001" ? 86400 : null,
119
- pluginCount: bot.id === "inst-001" ? 2 : bot.id === "inst-002" ? 1 : 3,
120
- sessionCount: bot.id === "inst-001" ? 5 : 0,
121
- provider: bot.id === "inst-001" ? "anthropic" : "openai",
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 } = await vi.importActual<
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, within } from "@testing-library/react";
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 buy credits panel with tiers", async () => {
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
- const positiveAmount = await screen.findByText("+$5.00");
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 load more button when there is a next cursor", async () => {
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("loads next page of transactions on load more click", async () => {
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
- const loadMoreBtn = await screen.findByRole("button", { name: "Load more" });
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 nav", () => {
363
- it("renders Credits navigation link", async () => {
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("Credits")).toBeInTheDocument();
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
- <div {...props}>{children}</div>
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
- data.MARKETPLACE_TEST_PLUGINS;
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