Spaces:
Build error
Build error
| import { render, screen, waitFor, within } from "@testing-library/react"; | |
| import { beforeEach, describe, expect, it, vi } from "vitest"; | |
| import userEvent from "@testing-library/user-event"; | |
| import { QueryClientProvider, QueryClient } from "@tanstack/react-query"; | |
| import { setupStore } from "test-utils"; | |
| import { Provider } from "react-redux"; | |
| import { createRoutesStub, Outlet } from "react-router"; | |
| import OpenHands from "#/api/open-hands"; | |
| import { GitRepository } from "#/types/git"; | |
| import { RepoConnector } from "#/components/features/home/repo-connector"; | |
| import { MOCK_DEFAULT_USER_SETTINGS } from "#/mocks/handlers"; | |
| const renderRepoConnector = () => { | |
| const mockRepoSelection = vi.fn(); | |
| const RouterStub = createRoutesStub([ | |
| { | |
| Component: () => <RepoConnector onRepoSelection={mockRepoSelection} />, | |
| path: "/", | |
| }, | |
| { | |
| Component: () => <div data-testid="conversation-screen" />, | |
| path: "/conversations/:conversationId", | |
| }, | |
| { | |
| Component: () => <Outlet />, | |
| path: "/settings", | |
| children: [ | |
| { | |
| Component: () => <div data-testid="settings-screen" />, | |
| path: "/settings", | |
| }, | |
| { | |
| Component: () => <div data-testid="git-settings-screen" />, | |
| path: "/settings/git", | |
| }, | |
| ], | |
| }, | |
| ]); | |
| return render(<RouterStub />, { | |
| wrapper: ({ children }) => ( | |
| <Provider store={setupStore()}> | |
| <QueryClientProvider client={new QueryClient()}> | |
| {children} | |
| </QueryClientProvider> | |
| </Provider> | |
| ), | |
| }); | |
| }; | |
| const MOCK_RESPOSITORIES: GitRepository[] = [ | |
| { | |
| id: 1, | |
| full_name: "rbren/polaris", | |
| git_provider: "github", | |
| is_public: true, | |
| }, | |
| { | |
| id: 2, | |
| full_name: "All-Hands-AI/OpenHands", | |
| git_provider: "github", | |
| is_public: true, | |
| }, | |
| ]; | |
| beforeEach(() => { | |
| const getSettingsSpy = vi.spyOn(OpenHands, "getSettings"); | |
| getSettingsSpy.mockResolvedValue({ | |
| ...MOCK_DEFAULT_USER_SETTINGS, | |
| provider_tokens_set: { | |
| github: "some-token", | |
| gitlab: null, | |
| }, | |
| }); | |
| }); | |
| describe("RepoConnector", () => { | |
| it("should render the repository connector section", () => { | |
| renderRepoConnector(); | |
| screen.getByTestId("repo-connector"); | |
| }); | |
| it("should render the available repositories in the dropdown", async () => { | |
| const retrieveUserGitRepositoriesSpy = vi.spyOn( | |
| OpenHands, | |
| "retrieveUserGitRepositories", | |
| ); | |
| retrieveUserGitRepositoriesSpy.mockResolvedValue(MOCK_RESPOSITORIES); | |
| renderRepoConnector(); | |
| // Wait for the loading state to be replaced with the dropdown | |
| const dropdown = await waitFor(() => screen.getByTestId("repo-dropdown")); | |
| await userEvent.click(dropdown); | |
| await waitFor(() => { | |
| screen.getByText("rbren/polaris"); | |
| screen.getByText("All-Hands-AI/OpenHands"); | |
| }); | |
| }); | |
| it("should only enable the launch button if a repo is selected", async () => { | |
| const retrieveUserGitRepositoriesSpy = vi.spyOn( | |
| OpenHands, | |
| "retrieveUserGitRepositories", | |
| ); | |
| retrieveUserGitRepositoriesSpy.mockResolvedValue(MOCK_RESPOSITORIES); | |
| renderRepoConnector(); | |
| const launchButton = await screen.findByTestId("repo-launch-button"); | |
| expect(launchButton).toBeDisabled(); | |
| // Wait for the loading state to be replaced with the dropdown | |
| const dropdown = await waitFor(() => screen.getByTestId("repo-dropdown")); | |
| await userEvent.click(dropdown); | |
| await userEvent.click(screen.getByText("rbren/polaris")); | |
| expect(launchButton).toBeEnabled(); | |
| }); | |
| it("should render the 'add git(hub|lab) repos' links if saas mode", async () => { | |
| const getConfiSpy = vi.spyOn(OpenHands, "getConfig"); | |
| // @ts-expect-error - only return the APP_MODE | |
| getConfiSpy.mockResolvedValue({ | |
| APP_MODE: "saas", | |
| }); | |
| renderRepoConnector(); | |
| await screen.findByText("Add GitHub repos"); | |
| }); | |
| it("should not render the 'add git(hub|lab) repos' links if oss mode", async () => { | |
| const getConfiSpy = vi.spyOn(OpenHands, "getConfig"); | |
| // @ts-expect-error - only return the APP_MODE | |
| getConfiSpy.mockResolvedValue({ | |
| APP_MODE: "oss", | |
| }); | |
| renderRepoConnector(); | |
| expect(screen.queryByText("Add GitHub repos")).not.toBeInTheDocument(); | |
| expect(screen.queryByText("Add GitLab repos")).not.toBeInTheDocument(); | |
| }); | |
| it("should create a conversation and redirect with the selected repo when pressing the launch button", async () => { | |
| const createConversationSpy = vi.spyOn(OpenHands, "createConversation"); | |
| const retrieveUserGitRepositoriesSpy = vi.spyOn( | |
| OpenHands, | |
| "retrieveUserGitRepositories", | |
| ); | |
| retrieveUserGitRepositoriesSpy.mockResolvedValue(MOCK_RESPOSITORIES); | |
| renderRepoConnector(); | |
| const repoConnector = screen.getByTestId("repo-connector"); | |
| const launchButton = | |
| await within(repoConnector).findByTestId("repo-launch-button"); | |
| await userEvent.click(launchButton); | |
| // repo not selected yet | |
| expect(createConversationSpy).not.toHaveBeenCalled(); | |
| // select a repository from the dropdown | |
| const dropdown = await waitFor(() => | |
| within(repoConnector).getByTestId("repo-dropdown"), | |
| ); | |
| await userEvent.click(dropdown); | |
| const repoOption = screen.getByText("rbren/polaris"); | |
| await userEvent.click(repoOption); | |
| await userEvent.click(launchButton); | |
| expect(createConversationSpy).toHaveBeenCalledExactlyOnceWith( | |
| "rbren/polaris", | |
| "github", | |
| undefined, | |
| [], | |
| undefined, | |
| undefined, | |
| undefined, | |
| ); | |
| }); | |
| it("should change the launch button text to 'Loading...' when creating a conversation", async () => { | |
| const retrieveUserGitRepositoriesSpy = vi.spyOn( | |
| OpenHands, | |
| "retrieveUserGitRepositories", | |
| ); | |
| retrieveUserGitRepositoriesSpy.mockResolvedValue(MOCK_RESPOSITORIES); | |
| renderRepoConnector(); | |
| const launchButton = await screen.findByTestId("repo-launch-button"); | |
| // Wait for the loading state to be replaced with the dropdown | |
| const dropdown = await waitFor(() => screen.getByTestId("repo-dropdown")); | |
| await userEvent.click(dropdown); | |
| await userEvent.click(screen.getByText("rbren/polaris")); | |
| await userEvent.click(launchButton); | |
| expect(launchButton).toBeDisabled(); | |
| expect(launchButton).toHaveTextContent(/Loading/i); | |
| }); | |
| it("should not display a button to settings if the user is signed in with their git provider", async () => { | |
| renderRepoConnector(); | |
| await waitFor(() => { | |
| expect( | |
| screen.queryByTestId("navigate-to-settings-button"), | |
| ).not.toBeInTheDocument(); | |
| }); | |
| }); | |
| it("should display a button to settings if the user needs to sign in with their git provider", async () => { | |
| const getSettingsSpy = vi.spyOn(OpenHands, "getSettings"); | |
| getSettingsSpy.mockResolvedValue({ | |
| ...MOCK_DEFAULT_USER_SETTINGS, | |
| provider_tokens_set: {}, | |
| }); | |
| renderRepoConnector(); | |
| const goToSettingsButton = await screen.findByTestId( | |
| "navigate-to-settings-button", | |
| ); | |
| const dropdown = screen.queryByTestId("repo-dropdown"); | |
| const launchButton = screen.queryByTestId("repo-launch-button"); | |
| const providerLinks = screen.queryAllByText(/add git(hub|lab) repos/i); | |
| expect(dropdown).not.toBeInTheDocument(); | |
| expect(launchButton).not.toBeInTheDocument(); | |
| expect(providerLinks.length).toBe(0); | |
| expect(goToSettingsButton).toBeInTheDocument(); | |
| await userEvent.click(goToSettingsButton); | |
| await screen.findByTestId("git-settings-screen"); | |
| }); | |
| }); | |