mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
This just implements a basic sign-in flow, using the new endpoints in #29 :  This brings over several dependencies that are necessary: - `formik` - `yep` Ports over some v1 code to bootstrap it: - `FormTextField` - `PasswordField` - `CoderIcon` And implements basic sign-in: Fixes #37 Fixes #43 This does not implement it navbar integration (importantly - there is no way to sign out yet, unless you manually delete your `session_token`). I'll do that in the next PR - figured this was big enough to get reviewed.
101 lines
3.1 KiB
TypeScript
101 lines
3.1 KiB
TypeScript
import singletonRouter from "next/router"
|
|
import mockRouter from "next-router-mock"
|
|
import React from "react"
|
|
import { SWRConfig } from "swr"
|
|
import { render, screen, waitFor } from "@testing-library/react"
|
|
|
|
import { User, UserProvider, useUser } from "./UserContext"
|
|
|
|
namespace Helpers {
|
|
// Helper component that renders out the state of the `useUser` hook.
|
|
// It just renders simple text in the 'error', 'me', and 'loading' states,
|
|
// so that the test can get a peak at the state of the hook.
|
|
const TestComponent: React.FC<{ redirectOnFailure: boolean }> = ({ redirectOnFailure }) => {
|
|
const { me, error } = useUser(redirectOnFailure)
|
|
|
|
if (error) {
|
|
return <div>{`Error: ${error.toString()}`}</div>
|
|
}
|
|
if (me) {
|
|
return <div>{`Me: ${me.toString()}`}</div>
|
|
}
|
|
|
|
return <div>Loading</div>
|
|
}
|
|
|
|
// Helper to render a userContext, and all the scaffolding needed
|
|
// (an SWRConfig as well as a UserPRovider)
|
|
export const renderUserContext = (
|
|
simulatedRequest: () => Promise<User>,
|
|
redirectOnFailure: boolean,
|
|
): React.ReactElement => {
|
|
return (
|
|
// Set up an SWRConfig that works for testing - we'll simulate a request,
|
|
// and set up the cache to reset every test.
|
|
<SWRConfig
|
|
value={{
|
|
fetcher: simulatedRequest,
|
|
// Reset cache for every test. Without this, requests will be cached between test cases.
|
|
provider: () => new Map(),
|
|
}}
|
|
>
|
|
<UserProvider>
|
|
<TestComponent redirectOnFailure={redirectOnFailure} />
|
|
</UserProvider>
|
|
</SWRConfig>
|
|
)
|
|
}
|
|
|
|
export const mockUser: User = {
|
|
id: "test-user-id",
|
|
username: "TestUser",
|
|
email: "test@coder.com",
|
|
created_at: "",
|
|
}
|
|
}
|
|
|
|
describe("UserContext", () => {
|
|
const failingRequest = () => Promise.reject("Failed to load user")
|
|
const successfulRequest = () => Promise.resolve(Helpers.mockUser)
|
|
|
|
// Reset the router to '/' before every test
|
|
beforeEach(() => {
|
|
mockRouter.setCurrentUrl("/")
|
|
})
|
|
|
|
it("shouldn't redirect if user fails to load and redirectOnFailure is false", async () => {
|
|
// When
|
|
render(Helpers.renderUserContext(failingRequest, false))
|
|
|
|
// Then
|
|
// Verify we get an error message
|
|
await waitFor(() => {
|
|
expect(screen.queryByText("Error:", { exact: false })).toBeDefined()
|
|
})
|
|
// ...and the route should be unchanged
|
|
expect(singletonRouter).toMatchObject({ asPath: "/" })
|
|
})
|
|
|
|
it("should redirect if user fails to load and redirectOnFailure is true", async () => {
|
|
// When
|
|
render(Helpers.renderUserContext(failingRequest, true))
|
|
|
|
// Then
|
|
// Verify we route to the login page
|
|
await waitFor(() => expect(singletonRouter).toMatchObject({ asPath: "/login?redirect=%2F" }))
|
|
})
|
|
|
|
it("should not redirect if user loads and redirectOnFailure is true", async () => {
|
|
// When
|
|
render(Helpers.renderUserContext(successfulRequest, true))
|
|
|
|
// Then
|
|
// Verify the user is rendered
|
|
await waitFor(() => {
|
|
expect(screen.queryByText("Me:", { exact: false })).toBeDefined()
|
|
})
|
|
// ...and the route should be unchanged
|
|
expect(singletonRouter).toMatchObject({ asPath: "/" })
|
|
})
|
|
})
|