Spaces:
Build error
Build error
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest"; | |
import { createRoutesStub } from "react-router"; | |
import { screen, waitFor, within } from "@testing-library/react"; | |
import { | |
createAxiosNotFoundErrorObject, | |
renderWithProviders, | |
} from "test-utils"; | |
import userEvent from "@testing-library/user-event"; | |
import MainApp from "#/routes/root-layout"; | |
import i18n from "#/i18n"; | |
import * as CaptureConsent from "#/utils/handle-capture-consent"; | |
import OpenHands from "#/api/open-hands"; | |
import * as ToastHandlers from "#/utils/custom-toast-handlers"; | |
describe("frontend/routes/_oh", () => { | |
const RouteStub = createRoutesStub([{ Component: MainApp, path: "/" }]); | |
const { userIsAuthenticatedMock, settingsAreUpToDateMock } = vi.hoisted( | |
() => ({ | |
userIsAuthenticatedMock: vi.fn(), | |
settingsAreUpToDateMock: vi.fn(), | |
}), | |
); | |
beforeAll(() => { | |
vi.mock("#/utils/user-is-authenticated", () => ({ | |
userIsAuthenticated: userIsAuthenticatedMock.mockReturnValue(true), | |
})); | |
vi.mock("#/services/settings", async (importOriginal) => ({ | |
...(await importOriginal<typeof import("#/services/settings")>()), | |
settingsAreUpToDate: settingsAreUpToDateMock, | |
})); | |
}); | |
afterEach(() => { | |
vi.clearAllMocks(); | |
localStorage.clear(); | |
}); | |
it("should render", async () => { | |
renderWithProviders(<RouteStub />); | |
await screen.findByTestId("root-layout"); | |
}); | |
it.skip("should render the AI config modal if settings are not up-to-date", async () => { | |
settingsAreUpToDateMock.mockReturnValue(false); | |
renderWithProviders(<RouteStub />); | |
await screen.findByTestId("ai-config-modal"); | |
}); | |
it("should not render the AI config modal if the settings are up-to-date", async () => { | |
settingsAreUpToDateMock.mockReturnValue(true); | |
renderWithProviders(<RouteStub />); | |
await waitFor(() => { | |
expect(screen.queryByTestId("ai-config-modal")).not.toBeInTheDocument(); | |
}); | |
}); | |
// FIXME: This test fails when it shouldn't be, please investigate | |
it.skip("should render and capture the user's consent if oss mode", async () => { | |
const user = userEvent.setup(); | |
const getConfigSpy = vi.spyOn(OpenHands, "getConfig"); | |
const getSettingsSpy = vi.spyOn(OpenHands, "getSettings"); | |
const handleCaptureConsentSpy = vi.spyOn( | |
CaptureConsent, | |
"handleCaptureConsent", | |
); | |
getConfigSpy.mockResolvedValue({ | |
APP_MODE: "oss", | |
GITHUB_CLIENT_ID: "test-id", | |
POSTHOG_CLIENT_KEY: "test-key", | |
FEATURE_FLAGS: { | |
ENABLE_BILLING: false, | |
HIDE_LLM_SETTINGS: false, | |
}, | |
}); | |
// @ts-expect-error - We only care about the user_consents_to_analytics field | |
getSettingsSpy.mockResolvedValue({ | |
user_consents_to_analytics: null, | |
}); | |
renderWithProviders(<RouteStub />); | |
// The user has not consented to tracking | |
const consentForm = await screen.findByTestId("user-capture-consent-form"); | |
expect(handleCaptureConsentSpy).not.toHaveBeenCalled(); | |
const submitButton = within(consentForm).getByRole("button", { | |
name: /confirm preferences/i, | |
}); | |
await user.click(submitButton); | |
// The user has now consented to tracking | |
expect(handleCaptureConsentSpy).toHaveBeenCalledWith(true); | |
expect( | |
screen.queryByTestId("user-capture-consent-form"), | |
).not.toBeInTheDocument(); | |
}); | |
it("should not render the user consent form if saas mode", async () => { | |
const getConfigSpy = vi.spyOn(OpenHands, "getConfig"); | |
getConfigSpy.mockResolvedValue({ | |
APP_MODE: "saas", | |
GITHUB_CLIENT_ID: "test-id", | |
POSTHOG_CLIENT_KEY: "test-key", | |
FEATURE_FLAGS: { | |
ENABLE_BILLING: false, | |
HIDE_LLM_SETTINGS: false, | |
}, | |
}); | |
renderWithProviders(<RouteStub />); | |
await waitFor(() => { | |
expect( | |
screen.queryByTestId("user-capture-consent-form"), | |
).not.toBeInTheDocument(); | |
}); | |
}); | |
// TODO: Likely failing due to how tokens are now handled in context. Move to e2e tests | |
it.skip("should render a new project button if a token is set", async () => { | |
localStorage.setItem("token", "test-token"); | |
const { rerender } = renderWithProviders(<RouteStub />); | |
await screen.findByTestId("new-project-button"); | |
localStorage.removeItem("token"); | |
rerender(<RouteStub />); | |
await waitFor(() => { | |
expect( | |
screen.queryByTestId("new-project-button"), | |
).not.toBeInTheDocument(); | |
}); | |
}); | |
// TODO: Move to e2e tests | |
it.skip("should update the i18n language when the language settings change", async () => { | |
const changeLanguageSpy = vi.spyOn(i18n, "changeLanguage"); | |
const { rerender } = renderWithProviders(<RouteStub />); | |
// The default language is English | |
expect(changeLanguageSpy).toHaveBeenCalledWith("en"); | |
localStorage.setItem("LANGUAGE", "es"); | |
rerender(<RouteStub />); | |
expect(changeLanguageSpy).toHaveBeenCalledWith("es"); | |
rerender(<RouteStub />); | |
// The language has not changed, so the spy should not have been called again | |
expect(changeLanguageSpy).toHaveBeenCalledTimes(2); | |
}); | |
// FIXME: logoutCleanup has been replaced with a hook | |
it.skip("should call logoutCleanup after a logout", async () => { | |
const user = userEvent.setup(); | |
localStorage.setItem("ghToken", "test-token"); | |
// const logoutCleanupSpy = vi.spyOn(LogoutCleanup, "logoutCleanup"); | |
renderWithProviders(<RouteStub />); | |
const userActions = await screen.findByTestId("user-actions"); | |
const userAvatar = within(userActions).getByTestId("user-avatar"); | |
await user.click(userAvatar); | |
const logout = within(userActions).getByRole("button", { name: /logout/i }); | |
await user.click(logout); | |
// expect(logoutCleanupSpy).toHaveBeenCalled(); | |
expect(localStorage.getItem("ghToken")).toBeNull(); | |
}); | |
it("should render a you're in toast if it is a new user and in saas mode", async () => { | |
const getConfigSpy = vi.spyOn(OpenHands, "getConfig"); | |
const getSettingsSpy = vi.spyOn(OpenHands, "getSettings"); | |
const displaySuccessToastSpy = vi.spyOn( | |
ToastHandlers, | |
"displaySuccessToast", | |
); | |
getConfigSpy.mockResolvedValue({ | |
APP_MODE: "saas", | |
GITHUB_CLIENT_ID: "test-id", | |
POSTHOG_CLIENT_KEY: "test-key", | |
FEATURE_FLAGS: { | |
ENABLE_BILLING: false, | |
HIDE_LLM_SETTINGS: false, | |
}, | |
}); | |
getSettingsSpy.mockRejectedValue(createAxiosNotFoundErrorObject()); | |
renderWithProviders(<RouteStub />); | |
await waitFor(() => { | |
expect(displaySuccessToastSpy).toHaveBeenCalledWith("BILLING$YOURE_IN"); | |
expect(displaySuccessToastSpy).toHaveBeenCalledOnce(); | |
}); | |
}); | |
}); | |