diff --git a/frontend/src/features/accounts/api.ts b/frontend/src/features/accounts/api.ts index 656db72ea..ba79bde55 100644 --- a/frontend/src/features/accounts/api.ts +++ b/frontend/src/features/accounts/api.ts @@ -13,6 +13,8 @@ import { AccountRoutingPolicyUpdateRequestSchema, AccountRoutingPolicyUpdateResponseSchema, AccountTrendsResponseSchema, + AccountProbeRequestSchema, + AccountProbeResponseSchema, ManualOauthCallbackRequestSchema, ManualOauthCallbackResponseSchema, OauthCompleteRequestSchema, @@ -99,6 +101,15 @@ export function getAccountTrends(accountId: string) { ); } +export function probeAccount(accountId: string, payload?: unknown) { + const validated = payload === undefined ? undefined : AccountProbeRequestSchema.parse(payload); + return post( + `${ACCOUNTS_BASE_PATH}/${encodeURIComponent(accountId)}/probe`, + AccountProbeResponseSchema, + validated ? { body: validated } : undefined, + ); +} + export function exportAccountAuth(accountId: string) { return post( `${ACCOUNTS_BASE_PATH}/${encodeURIComponent(accountId)}/export/auth`, diff --git a/frontend/src/features/accounts/components/account-actions.test.tsx b/frontend/src/features/accounts/components/account-actions.test.tsx index 41f935d71..2aad534b6 100644 --- a/frontend/src/features/accounts/components/account-actions.test.tsx +++ b/frontend/src/features/accounts/components/account-actions.test.tsx @@ -1,4 +1,5 @@ import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; import { describe, expect, it, vi } from "vitest"; import { AccountActions } from "@/features/accounts/components/account-actions"; @@ -15,6 +16,7 @@ describe("AccountActions", () => { busy={false} onPause={vi.fn()} onResume={vi.fn()} + onProbe={vi.fn()} onDelete={vi.fn()} onReauth={vi.fn()} onExportAuth={vi.fn()} @@ -40,6 +42,7 @@ describe("AccountActions", () => { busy={false} onPause={vi.fn()} onResume={vi.fn()} + onProbe={vi.fn()} onDelete={vi.fn()} onReauth={onReauth} onExportAuth={vi.fn()} @@ -59,4 +62,63 @@ describe("AccountActions", () => { screen.queryByRole("combobox", { name: "Routing policy" }), ).not.toBeInTheDocument(); }); + + it("fires the per-account probe callback for active accounts", async () => { + const user = userEvent.setup(); + const account = createAccountSummary(); + const onProbe = vi.fn(); + + render( + , + ); + + await user.click(screen.getByRole("button", { name: "Force probe" })); + + expect(onProbe).toHaveBeenCalledWith(account.accountId); + expect(onProbe).toHaveBeenCalledTimes(1); + }); + + it.each(["paused", "deactivated"] as const)( + "disables force probe for %s accounts", + async (status) => { + const user = userEvent.setup(); + const account = createAccountSummary({ status }); + const onProbe = vi.fn(); + + render( + , + ); + + const button = screen.getByRole("button", { name: "Force probe" }); + expect(button).toBeDisabled(); + + await user.click(button); + + expect(onProbe).not.toHaveBeenCalled(); + }, + ); }); diff --git a/frontend/src/features/accounts/components/account-actions.tsx b/frontend/src/features/accounts/components/account-actions.tsx index 03ea1acfd..de70df4ff 100644 --- a/frontend/src/features/accounts/components/account-actions.tsx +++ b/frontend/src/features/accounts/components/account-actions.tsx @@ -1,4 +1,5 @@ import { + Activity, Download, Pause, Play, @@ -28,6 +29,7 @@ export type AccountActionsProps = { busy: boolean; onPause: (accountId: string) => void; onResume: (accountId: string) => void; + onProbe: (accountId: string) => void; onDelete: (accountId: string) => void; onReauth: () => void; onExportAuth: (accountId: string) => void; @@ -44,6 +46,7 @@ export function AccountActions({ busy, onPause, onResume, + onProbe, onDelete, onReauth, onExportAuth, @@ -53,6 +56,8 @@ export function AccountActions({ }: AccountActionsProps) { const showOperatorRecoveryAction = account.status === "reauth_required" || account.status === "deactivated"; + const probeDisabled = + busy || account.status === "paused" || showOperatorRecoveryAction; return (
@@ -142,6 +147,18 @@ export function AccountActions({ ) : null} + +