mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-30 03:00:41 -04:00
test(frontend): extract resolveSessionDryRun to helper + add coverage
- Extract session dry_run resolution logic from useChatSession.ts into resolveSessionDryRun() helper in helpers.ts for testability - Add 6 unit tests covering null/undefined/non-200/false/missing/true branches of resolveSessionDryRun in __tests__/helpers.test.ts - Remove unused isDryRun destructure from CopilotPage.tsx (now only sessionDryRun is used for the session-scoped test mode banner) - Fix patch coverage gap: new sessionDryRun logic is now fully covered
This commit is contained in:
@@ -113,8 +113,7 @@ export function CopilotPage() {
|
||||
// Rate limit reset
|
||||
rateLimitMessage,
|
||||
dismissRateLimit,
|
||||
// Dry run dev toggle
|
||||
isDryRun,
|
||||
// Dry run session state
|
||||
sessionDryRun,
|
||||
} = useCopilotPage();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { IMPERSONATION_HEADER_NAME } from "@/lib/constants";
|
||||
import { getCopilotAuthHeaders } from "../helpers";
|
||||
import { getCopilotAuthHeaders, resolveSessionDryRun } from "../helpers";
|
||||
|
||||
vi.mock("@/lib/supabase/actions", () => ({
|
||||
getWebSocketToken: vi.fn(),
|
||||
@@ -16,6 +16,42 @@ import { getSystemHeaders } from "@/lib/impersonation";
|
||||
const mockGetWebSocketToken = vi.mocked(getWebSocketToken);
|
||||
const mockGetSystemHeaders = vi.mocked(getSystemHeaders);
|
||||
|
||||
describe("resolveSessionDryRun", () => {
|
||||
it("returns false when queryData is null", () => {
|
||||
expect(resolveSessionDryRun(null)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when queryData is undefined", () => {
|
||||
expect(resolveSessionDryRun(undefined)).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when status is not 200", () => {
|
||||
expect(resolveSessionDryRun({ status: 404 })).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when status is 200 but metadata.dry_run is false", () => {
|
||||
expect(
|
||||
resolveSessionDryRun({
|
||||
status: 200,
|
||||
data: { metadata: { dry_run: false } },
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("returns false when status is 200 but metadata is missing", () => {
|
||||
expect(resolveSessionDryRun({ status: 200, data: {} })).toBe(false);
|
||||
});
|
||||
|
||||
it("returns true when status is 200 and metadata.dry_run is true", () => {
|
||||
expect(
|
||||
resolveSessionDryRun({
|
||||
status: 200,
|
||||
data: { metadata: { dry_run: true } },
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getCopilotAuthHeaders", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
@@ -52,6 +52,24 @@ export function parseSessionIDs(raw: string | null | undefined): Set<string> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the actual dry_run value for a session from the raw API response.
|
||||
* Returns true only when the session response is a 200 with metadata.dry_run === true.
|
||||
* Returns false for missing/non-200 responses so callers never show a stale
|
||||
* preference value when the real session state is unknown.
|
||||
*/
|
||||
export function resolveSessionDryRun(queryData: unknown): boolean {
|
||||
if (
|
||||
queryData == null ||
|
||||
typeof queryData !== "object" ||
|
||||
!("status" in queryData) ||
|
||||
(queryData as { status: unknown }).status !== 200
|
||||
)
|
||||
return false;
|
||||
const d = queryData as { data?: { metadata?: { dry_run?: unknown } } };
|
||||
return d.data?.metadata?.dry_run === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a refetchSession result indicates the backend still has an
|
||||
* active SSE stream for this session.
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
||||
import { parseAsString, useQueryState } from "nuqs";
|
||||
import { useEffect, useMemo, useRef } from "react";
|
||||
import { convertChatSessionMessagesToUiMessages } from "./helpers/convertChatSessionToUiMessages";
|
||||
import { resolveSessionDryRun } from "./helpers";
|
||||
|
||||
interface UseChatSessionOptions {
|
||||
dryRun?: boolean;
|
||||
@@ -170,10 +171,10 @@ export function useChatSession({ dryRun = false }: UseChatSessionOptions = {}) {
|
||||
// Design intent: the global isDryRun store is only used when creating NEW
|
||||
// sessions. Once a session exists, its dry_run flag is immutable and should
|
||||
// be read from here rather than from the store, which may have changed.
|
||||
const sessionDryRun = useMemo(() => {
|
||||
if (sessionQuery.data?.status !== 200) return false;
|
||||
return sessionQuery.data.data.metadata?.dry_run === true;
|
||||
}, [sessionQuery.data]);
|
||||
const sessionDryRun = useMemo(
|
||||
() => resolveSessionDryRun(sessionQuery.data),
|
||||
[sessionQuery.data],
|
||||
);
|
||||
|
||||
return {
|
||||
sessionId,
|
||||
|
||||
Reference in New Issue
Block a user