OpenHands / frontend /__tests__ /components /features /home /repo-selection-form.test.tsx
Backup-bdg's picture
Upload 565 files
b59aa07 verified
import { render, screen } from "@testing-library/react";
import { describe, expect, vi, beforeEach, it } from "vitest";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import userEvent from "@testing-library/user-event";
import { RepositorySelectionForm } from "../../../../src/components/features/home/repo-selection-form";
import OpenHands from "#/api/open-hands";
import { GitRepository } from "#/types/git";
// Create mock functions
const mockUseUserRepositories = vi.fn();
const mockUseCreateConversation = vi.fn();
const mockUseIsCreatingConversation = vi.fn();
const mockUseTranslation = vi.fn();
const mockUseAuth = vi.fn();
// Setup default mock returns
mockUseUserRepositories.mockReturnValue({
data: [],
isLoading: false,
isError: false,
});
mockUseCreateConversation.mockReturnValue({
mutate: vi.fn(),
isPending: false,
isSuccess: false,
});
mockUseIsCreatingConversation.mockReturnValue(false);
mockUseTranslation.mockReturnValue({ t: (key: string) => key });
mockUseAuth.mockReturnValue({
isAuthenticated: true,
isLoading: false,
providersAreSet: true,
user: {
id: 1,
login: "testuser",
avatar_url: "https://example.com/avatar.png",
name: "Test User",
email: "[email protected]",
company: "Test Company",
},
login: vi.fn(),
logout: vi.fn(),
});
vi.mock("#/hooks/mutation/use-create-conversation", () => ({
useCreateConversation: () => mockUseCreateConversation(),
}));
vi.mock("#/hooks/use-is-creating-conversation", () => ({
useIsCreatingConversation: () => mockUseIsCreatingConversation(),
}));
vi.mock("react-i18next", () => ({
useTranslation: () => mockUseTranslation(),
}));
vi.mock("#/context/auth-context", () => ({
useAuth: () => mockUseAuth(),
}));
vi.mock("#/hooks/use-debounce", () => ({
useDebounce: (value: string) => value,
}));
const mockOnRepoSelection = vi.fn();
const renderForm = () =>
render(<RepositorySelectionForm onRepoSelection={mockOnRepoSelection} />, {
wrapper: ({ children }) => (
<QueryClientProvider
client={
new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
})
}
>
{children}
</QueryClientProvider>
),
});
describe("RepositorySelectionForm", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("shows loading indicator when repositories are being fetched", () => {
const MOCK_REPOS: GitRepository[] = [
{
id: 1,
full_name: "user/repo1",
git_provider: "github",
is_public: true,
},
{
id: 2,
full_name: "user/repo2",
git_provider: "github",
is_public: true,
},
];
const retrieveUserGitRepositoriesSpy = vi.spyOn(
OpenHands,
"retrieveUserGitRepositories",
);
retrieveUserGitRepositoriesSpy.mockResolvedValue(MOCK_REPOS);
renderForm();
// Check if loading indicator is displayed
expect(screen.getByTestId("repo-dropdown-loading")).toBeInTheDocument();
expect(screen.getByText("HOME$LOADING_REPOSITORIES")).toBeInTheDocument();
});
it("shows dropdown when repositories are loaded", async () => {
const MOCK_REPOS: GitRepository[] = [
{
id: 1,
full_name: "user/repo1",
git_provider: "github",
is_public: true,
},
{
id: 2,
full_name: "user/repo2",
git_provider: "github",
is_public: true,
},
];
const retrieveUserGitRepositoriesSpy = vi.spyOn(
OpenHands,
"retrieveUserGitRepositories",
);
retrieveUserGitRepositoriesSpy.mockResolvedValue(MOCK_REPOS);
renderForm();
expect(await screen.findByTestId("repo-dropdown")).toBeInTheDocument();
});
it("shows error message when repository fetch fails", async () => {
const retrieveUserGitRepositoriesSpy = vi.spyOn(
OpenHands,
"retrieveUserGitRepositories",
);
retrieveUserGitRepositoriesSpy.mockRejectedValue(
new Error("Failed to load"),
);
renderForm();
expect(
await screen.findByTestId("repo-dropdown-error"),
).toBeInTheDocument();
expect(
screen.getByText("HOME$FAILED_TO_LOAD_REPOSITORIES"),
).toBeInTheDocument();
});
it("should call the search repos API when searching a URL", async () => {
const MOCK_REPOS: GitRepository[] = [
{
id: 1,
full_name: "user/repo1",
git_provider: "github",
is_public: true,
},
{
id: 2,
full_name: "user/repo2",
git_provider: "github",
is_public: true,
},
];
const MOCK_SEARCH_REPOS: GitRepository[] = [
{
id: 3,
full_name: "kubernetes/kubernetes",
git_provider: "github",
is_public: true,
},
];
const searchGitReposSpy = vi.spyOn(OpenHands, "searchGitRepositories");
const retrieveUserGitRepositoriesSpy = vi.spyOn(
OpenHands,
"retrieveUserGitRepositories",
);
searchGitReposSpy.mockResolvedValue(MOCK_SEARCH_REPOS);
retrieveUserGitRepositoriesSpy.mockResolvedValue(MOCK_REPOS);
renderForm();
const input = await screen.findByTestId("repo-dropdown");
await userEvent.click(input);
for (const repo of MOCK_REPOS) {
expect(screen.getByText(repo.full_name)).toBeInTheDocument();
}
expect(
screen.queryByText(MOCK_SEARCH_REPOS[0].full_name),
).not.toBeInTheDocument();
expect(searchGitReposSpy).not.toHaveBeenCalled();
await userEvent.type(input, "https://github.com/kubernetes/kubernetes");
expect(searchGitReposSpy).toHaveBeenLastCalledWith(
"kubernetes/kubernetes",
3,
);
expect(
screen.getByText(MOCK_SEARCH_REPOS[0].full_name),
).toBeInTheDocument();
for (const repo of MOCK_REPOS) {
expect(screen.queryByText(repo.full_name)).not.toBeInTheDocument();
}
});
it("should call onRepoSelection when a searched repository is selected", async () => {
const MOCK_SEARCH_REPOS: GitRepository[] = [
{
id: 3,
full_name: "kubernetes/kubernetes",
git_provider: "github",
is_public: true,
},
];
const searchGitReposSpy = vi.spyOn(OpenHands, "searchGitRepositories");
searchGitReposSpy.mockResolvedValue(MOCK_SEARCH_REPOS);
renderForm();
const input = await screen.findByTestId("repo-dropdown");
await userEvent.type(input, "https://github.com/kubernetes/kubernetes");
expect(searchGitReposSpy).toHaveBeenLastCalledWith(
"kubernetes/kubernetes",
3,
);
const searchedRepo = screen.getByText(MOCK_SEARCH_REPOS[0].full_name);
expect(searchedRepo).toBeInTheDocument();
await userEvent.click(searchedRepo);
expect(mockOnRepoSelection).toHaveBeenCalledWith(
MOCK_SEARCH_REPOS[0].full_name,
);
});
});