import "@testing-library/jest-dom"; import { act, render, screen } from "@testing-library/react"; import React from "react"; import Explorer from "../../Explorer"; import { CopyJobMigrationType } from "../Enums/CopyJobEnums"; import CopyJobContextProvider, { CopyJobContext, useCopyJobContext } from "./CopyJobContext"; jest.mock("UserContext", () => ({ userContext: { subscriptionId: "test-subscription-id", databaseAccount: { id: "/subscriptions/test-sub/resourceGroups/test-rg/providers/Microsoft.DocumentDB/databaseAccounts/test-account", name: "test-account", location: "East US", kind: "GlobalDocumentDB", }, }, })); describe("CopyJobContext", () => { let mockExplorer: Explorer; beforeEach(() => { mockExplorer = {} as Explorer; }); afterEach(() => { jest.clearAllMocks(); }); describe("CopyJobContextProvider", () => { it("should render children correctly", () => { render(
Test Child
, ); expect(screen.getByTestId("test-child")).toBeInTheDocument(); expect(screen.getByTestId("test-child")).toHaveTextContent("Test Child"); }); it("should initialize with default state", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue).toBeDefined(); expect(contextValue.copyJobState).toEqual({ jobName: "", migrationType: CopyJobMigrationType.Offline, source: { subscription: null, account: null, databaseId: "", containerId: "", }, target: { subscriptionId: "test-subscription-id", account: { id: "/subscriptions/test-sub/resourceGroups/test-rg/providers/Microsoft.DocumentDB/databaseAccounts/test-account", name: "test-account", location: "East US", kind: "GlobalDocumentDB", }, databaseId: "", containerId: "", }, sourceReadAccessFromTarget: false, }); expect(contextValue.flow).toBeNull(); expect(contextValue.contextError).toBeNull(); expect(contextValue.explorer).toBe(mockExplorer); }); it("should provide setCopyJobState function", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue.setCopyJobState).toBeDefined(); expect(typeof contextValue.setCopyJobState).toBe("function"); }); it("should provide setFlow function", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue.setFlow).toBeDefined(); expect(typeof contextValue.setFlow).toBe("function"); }); it("should provide setContextError function", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue.setContextError).toBeDefined(); expect(typeof contextValue.setContextError).toBe("function"); }); it("should provide resetCopyJobState function", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue.resetCopyJobState).toBeDefined(); expect(typeof contextValue.resetCopyJobState).toBe("function"); }); it("should update copyJobState when setCopyJobState is called", () => { let contextValue: any; const TestComponent = (): JSX.Element => { const context = useCopyJobContext(); contextValue = context; return ( ); }; render( , ); const button = screen.getByText("Update Job"); act(() => { button.click(); }); expect(contextValue.copyJobState.jobName).toBe("test-job"); expect(contextValue.copyJobState.migrationType).toBe(CopyJobMigrationType.Online); }); it("should update flow when setFlow is called", () => { let contextValue: any; const TestComponent = (): JSX.Element => { const context = useCopyJobContext(); contextValue = context; const handleSetFlow = (): void => { context.setFlow({ currentScreen: "source-selection" }); }; return ; }; render( , ); expect(contextValue.flow).toBeNull(); const button = screen.getByText("Set Flow"); act(() => { button.click(); }); expect(contextValue.flow).toEqual({ currentScreen: "source-selection" }); }); it("should update contextError when setContextError is called", () => { let contextValue: any; const TestComponent = (): JSX.Element => { const context = useCopyJobContext(); contextValue = context; return ; }; render( , ); expect(contextValue.contextError).toBeNull(); const button = screen.getByText("Set Error"); act(() => { button.click(); }); expect(contextValue.contextError).toBe("Test error message"); }); it("should reset copyJobState when resetCopyJobState is called", () => { let contextValue: any; const TestComponent = (): JSX.Element => { const context = useCopyJobContext(); contextValue = context; const handleUpdate = (): void => { context.setCopyJobState({ ...context.copyJobState, jobName: "modified-job", migrationType: CopyJobMigrationType.Online, source: { ...context.copyJobState.source, databaseId: "test-db", containerId: "test-container", }, }); }; return ( <> ); }; render( , ); const updateButton = screen.getByText("Update"); act(() => { updateButton.click(); }); expect(contextValue.copyJobState.jobName).toBe("modified-job"); expect(contextValue.copyJobState.migrationType).toBe(CopyJobMigrationType.Online); expect(contextValue.copyJobState.source.databaseId).toBe("test-db"); const resetButton = screen.getByText("Reset"); act(() => { resetButton.click(); }); expect(contextValue.copyJobState.jobName).toBe(""); expect(contextValue.copyJobState.migrationType).toBe(CopyJobMigrationType.Offline); expect(contextValue.copyJobState.source.databaseId).toBe(""); expect(contextValue.copyJobState.source.containerId).toBe(""); }); it("should maintain explorer reference", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue.explorer).toBe(mockExplorer); }); it("should handle multiple state updates correctly", () => { let contextValue: any; const TestComponent = (): JSX.Element => { const context = useCopyJobContext(); contextValue = context; return ( <> ); }; render( , ); act(() => { screen.getByText("Update 1").click(); }); expect(contextValue.copyJobState.jobName).toBe("job-1"); act(() => { screen.getByText("Flow 1").click(); }); expect(contextValue.flow).toEqual({ currentScreen: "screen-1" }); act(() => { screen.getByText("Error 1").click(); }); expect(contextValue.contextError).toBe("error-1"); }); it("should handle partial state updates", () => { let contextValue: any; const TestComponent = (): JSX.Element => { const context = useCopyJobContext(); contextValue = context; const handlePartialUpdate = (): void => { context.setCopyJobState((prev) => ({ ...prev, jobName: "partial-update", })); }; return ; }; render( , ); const initialState = { ...contextValue.copyJobState }; act(() => { screen.getByText("Partial Update").click(); }); expect(contextValue.copyJobState.jobName).toBe("partial-update"); expect(contextValue.copyJobState.migrationType).toBe(initialState.migrationType); expect(contextValue.copyJobState.source).toEqual(initialState.source); expect(contextValue.copyJobState.target).toEqual(initialState.target); }); }); describe("useCopyJobContext", () => { it("should return context value when used within provider", () => { let contextValue: any; const TestComponent = (): null => { const context = useCopyJobContext(); contextValue = context; return null; }; render( , ); expect(contextValue).toBeDefined(); expect(contextValue.copyJobState).toBeDefined(); expect(contextValue.setCopyJobState).toBeDefined(); expect(contextValue.flow).toBeNull(); expect(contextValue.setFlow).toBeDefined(); expect(contextValue.contextError).toBeNull(); expect(contextValue.setContextError).toBeDefined(); expect(contextValue.resetCopyJobState).toBeDefined(); expect(contextValue.explorer).toBe(mockExplorer); }); it("should throw error when used outside provider", () => { const originalError = console.error; console.error = jest.fn(); const TestComponent = (): null => { useCopyJobContext(); return null; }; expect(() => { render(); }).toThrow("useCopyJobContext must be used within a CopyJobContextProvider"); console.error = originalError; }); it("should allow updating state through hook", () => { let contextValue: any; const TestComponent = (): JSX.Element => { const context = useCopyJobContext(); contextValue = context; return ( ); }; render( , ); act(() => { screen.getByText("Update").click(); }); expect(contextValue.copyJobState.jobName).toBe("hook-test-job"); }); it("should allow resetting state through hook", () => { let contextValue: any; const TestComponent = (): JSX.Element => { const context = useCopyJobContext(); contextValue = context; return ( <> ); }; render( , ); act(() => { screen.getByText("Modify").click(); }); expect(contextValue.copyJobState.jobName).toBe("modified"); expect(contextValue.copyJobState.source.databaseId).toBe("modified-db"); act(() => { screen.getByText("Reset").click(); }); expect(contextValue.copyJobState.jobName).toBe(""); expect(contextValue.copyJobState.source.databaseId).toBe(""); }); it("should maintain state consistency across multiple components", () => { let contextValue1: any; let contextValue2: any; const TestComponent1 = (): JSX.Element => { const context = useCopyJobContext(); contextValue1 = context; return ( ); }; const TestComponent2 = (): JSX.Element => { const context = useCopyJobContext(); contextValue2 = context; return
Component 2
; }; render( , ); expect(contextValue1.copyJobState).toEqual(contextValue2.copyJobState); act(() => { screen.getByText("Update From Component 1").click(); }); expect(contextValue1.copyJobState.jobName).toBe("shared-job"); expect(contextValue2.copyJobState.jobName).toBe("shared-job"); }); }); describe("Initial State", () => { it("should initialize with offline migration type", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue.copyJobState.migrationType).toBe(CopyJobMigrationType.Offline); }); it("should initialize source with userContext values", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue.copyJobState.source?.subscription?.subscriptionId).toBeUndefined(); expect(contextValue.copyJobState.source?.account?.name).toBeUndefined(); }); it("should initialize target with userContext values", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue.copyJobState.target.subscriptionId).toBe("test-subscription-id"); expect(contextValue.copyJobState.target.account.name).toBe("test-account"); }); it("should initialize sourceReadAccessFromTarget as false", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue.copyJobState.sourceReadAccessFromTarget).toBe(false); }); it("should initialize with empty database and container ids", () => { let contextValue: any; render( {(value) => { contextValue = value; return null; }} , ); expect(contextValue.copyJobState.source.databaseId).toBe(""); expect(contextValue.copyJobState.source.containerId).toBe(""); expect(contextValue.copyJobState.target.databaseId).toBe(""); expect(contextValue.copyJobState.target.containerId).toBe(""); }); }); });