mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: bump react-router-dom from 6.4.1 to 6.12.1 in /site (#7950)
* chore: bump react-router-dom from 6.4.1 to 6.12.1 in /site Bumps [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) from 6.4.1 to 6.12.1. - [Release notes](https://github.com/remix-run/react-router/releases) - [Changelog](https://github.com/remix-run/react-router/blob/main/packages/react-router-dom/CHANGELOG.md) - [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@6.12.1/packages/react-router-dom) --- updated-dependencies: - dependency-name: react-router-dom dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * fix what needs to be fixed * fix storybook --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: BrunoQuaresma <bruno_nonato_quaresma@hotmail.com>
This commit is contained in:
co-authored by
BrunoQuaresma
parent
6e598234b6
commit
33c0674d76
@@ -292,7 +292,7 @@ export const AppRouter: FC = () => {
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="/@:username">
|
||||
<Route path="/:username">
|
||||
<Route path=":workspace">
|
||||
<Route index element={<WorkspacePage />} />
|
||||
<Route
|
||||
@@ -316,7 +316,7 @@ export const AppRouter: FC = () => {
|
||||
|
||||
{/* Terminal and CLI auth pages don't have the dashboard layout */}
|
||||
<Route
|
||||
path="/@:username/:workspace/terminal"
|
||||
path="/:username/:workspace/terminal"
|
||||
element={<TerminalPage />}
|
||||
/>
|
||||
<Route path="cli-auth" element={<CliAuthenticationPage />} />
|
||||
|
||||
@@ -1,19 +1,6 @@
|
||||
import { fireEvent, render, screen } from "@testing-library/react"
|
||||
import { FC } from "react"
|
||||
import { WrapperComponent } from "../../../testHelpers/renderHelpers"
|
||||
import { fireEvent, screen } from "@testing-library/react"
|
||||
import { ConfirmDialog, ConfirmDialogProps } from "./ConfirmDialog"
|
||||
|
||||
namespace Helpers {
|
||||
export const Component: FC<React.PropsWithChildren<ConfirmDialogProps>> = (
|
||||
props: ConfirmDialogProps,
|
||||
) => {
|
||||
return (
|
||||
<WrapperComponent>
|
||||
<ConfirmDialog {...props} />
|
||||
</WrapperComponent>
|
||||
)
|
||||
}
|
||||
}
|
||||
import { render } from "testHelpers/renderHelpers"
|
||||
|
||||
describe("ConfirmDialog", () => {
|
||||
it("renders", () => {
|
||||
@@ -26,7 +13,7 @@ describe("ConfirmDialog", () => {
|
||||
}
|
||||
|
||||
// When
|
||||
render(<Helpers.Component {...props} />)
|
||||
render(<ConfirmDialog {...props} />)
|
||||
|
||||
// Then
|
||||
expect(screen.getByRole("dialog")).toBeDefined()
|
||||
@@ -43,7 +30,7 @@ describe("ConfirmDialog", () => {
|
||||
}
|
||||
|
||||
// When
|
||||
render(<Helpers.Component {...props} />)
|
||||
render(<ConfirmDialog {...props} />)
|
||||
|
||||
// Then
|
||||
expect(screen.queryByText("CANCEL")).toBeNull()
|
||||
@@ -61,7 +48,7 @@ describe("ConfirmDialog", () => {
|
||||
}
|
||||
|
||||
// When
|
||||
render(<Helpers.Component {...props} />)
|
||||
render(<ConfirmDialog {...props} />)
|
||||
|
||||
// Then
|
||||
expect(screen.getByText("CANCEL")).toBeDefined()
|
||||
@@ -79,7 +66,7 @@ describe("ConfirmDialog", () => {
|
||||
}
|
||||
|
||||
// When
|
||||
render(<Helpers.Component {...props} />)
|
||||
render(<ConfirmDialog {...props} />)
|
||||
|
||||
// Then
|
||||
expect(screen.getByText("CANCEL")).toBeDefined()
|
||||
@@ -98,7 +85,7 @@ describe("ConfirmDialog", () => {
|
||||
}
|
||||
|
||||
// When
|
||||
render(<Helpers.Component {...props} />)
|
||||
render(<ConfirmDialog {...props} />)
|
||||
|
||||
// Then
|
||||
expect(screen.queryByText("CANCEL")).toBeNull()
|
||||
@@ -116,7 +103,7 @@ describe("ConfirmDialog", () => {
|
||||
}
|
||||
|
||||
// When
|
||||
render(<Helpers.Component {...props} />)
|
||||
render(<ConfirmDialog {...props} />)
|
||||
fireEvent.click(screen.getByText("CANCEL"))
|
||||
|
||||
// Then
|
||||
@@ -138,7 +125,7 @@ describe("ConfirmDialog", () => {
|
||||
}
|
||||
|
||||
// When
|
||||
render(<Helpers.Component {...props} />)
|
||||
render(<ConfirmDialog {...props} />)
|
||||
fireEvent.click(screen.getByText("CONFIRM"))
|
||||
|
||||
// Then
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { ComponentMeta, Story } from "@storybook/react"
|
||||
import { MockUser, MockUserAgent } from "testHelpers/entities"
|
||||
import { UserCell, UserCellProps } from "./UserCell"
|
||||
|
||||
export default {
|
||||
title: "components/UserCell",
|
||||
component: UserCell,
|
||||
} as ComponentMeta<typeof UserCell>
|
||||
|
||||
const Template: Story<UserCellProps> = (args) => <UserCell {...args} />
|
||||
|
||||
export const AuditLogExample = Template.bind({})
|
||||
AuditLogExample.args = {
|
||||
Avatar: {
|
||||
username: MockUser.username,
|
||||
avatarURL: "",
|
||||
},
|
||||
caption: MockUserAgent.ip_address,
|
||||
primaryText: MockUser.email,
|
||||
onPrimaryTextSelect: () => {
|
||||
return
|
||||
},
|
||||
}
|
||||
|
||||
export const AuditLogEmptyUserExample = Template.bind({})
|
||||
AuditLogEmptyUserExample.args = {
|
||||
Avatar: {
|
||||
username: MockUser.username,
|
||||
avatarURL: "",
|
||||
},
|
||||
caption: MockUserAgent.ip_address,
|
||||
primaryText: "Deleted User",
|
||||
onPrimaryTextSelect: undefined,
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
import { fireEvent, render, screen } from "@testing-library/react"
|
||||
import { FC } from "react"
|
||||
import { MockUser, MockUserAgent } from "testHelpers/entities"
|
||||
import { WrapperComponent } from "../../testHelpers/renderHelpers"
|
||||
import { UserCell, UserCellProps } from "./UserCell"
|
||||
|
||||
namespace Helpers {
|
||||
export const Props: UserCellProps = {
|
||||
Avatar: {
|
||||
username: MockUser.username,
|
||||
avatarURL: "",
|
||||
},
|
||||
caption: MockUserAgent.ip_address,
|
||||
primaryText: MockUser.username,
|
||||
onPrimaryTextSelect: jest.fn(),
|
||||
}
|
||||
|
||||
export const Component: FC<React.PropsWithChildren<UserCellProps>> = (
|
||||
props,
|
||||
) => (
|
||||
<WrapperComponent>
|
||||
<UserCell {...props} />
|
||||
</WrapperComponent>
|
||||
)
|
||||
}
|
||||
|
||||
describe("UserCell", () => {
|
||||
// callbacks
|
||||
it("calls onPrimaryTextSelect when primaryText is clicked", () => {
|
||||
// Given
|
||||
const onPrimaryTextSelectMock = jest.fn()
|
||||
const props: UserCellProps = {
|
||||
...Helpers.Props,
|
||||
onPrimaryTextSelect: onPrimaryTextSelectMock,
|
||||
}
|
||||
|
||||
// When - click the user's email address
|
||||
render(<Helpers.Component {...props} />)
|
||||
fireEvent.click(screen.getByText(props.primaryText))
|
||||
|
||||
// Then - callback was fired once
|
||||
expect(onPrimaryTextSelectMock).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
// primaryText
|
||||
it("renders primaryText as a link when onPrimaryTextSelect is defined", () => {
|
||||
// Given
|
||||
const props: UserCellProps = Helpers.Props
|
||||
|
||||
// When
|
||||
render(<Helpers.Component {...props} />)
|
||||
const primaryTextNode = screen.getByText(props.primaryText)
|
||||
|
||||
// Then
|
||||
expect(primaryTextNode.tagName).toBe("A")
|
||||
})
|
||||
it("renders primaryText without a link when onPrimaryTextSelect is undefined", () => {
|
||||
// Given
|
||||
const props: UserCellProps = {
|
||||
...Helpers.Props,
|
||||
onPrimaryTextSelect: undefined,
|
||||
}
|
||||
|
||||
// When
|
||||
render(<Helpers.Component {...props} />)
|
||||
const primaryTextNode = screen.getByText(props.primaryText)
|
||||
|
||||
// Then
|
||||
expect(primaryTextNode.tagName).toBe("P")
|
||||
})
|
||||
|
||||
// caption
|
||||
it("renders caption", () => {
|
||||
// Given
|
||||
const caption = "definitely a caption"
|
||||
const props: UserCellProps = {
|
||||
...Helpers.Props,
|
||||
caption,
|
||||
}
|
||||
|
||||
// When
|
||||
render(<Helpers.Component {...props} />)
|
||||
|
||||
// Then
|
||||
expect(screen.getByText(caption)).toBeDefined()
|
||||
})
|
||||
})
|
||||
@@ -1,69 +0,0 @@
|
||||
import Box from "@mui/material/Box"
|
||||
import Link from "@mui/material/Link"
|
||||
import { makeStyles } from "@mui/styles"
|
||||
import Typography from "@mui/material/Typography"
|
||||
import { FC } from "react"
|
||||
import { UserAvatar, UserAvatarProps } from "../UserAvatar/UserAvatar"
|
||||
|
||||
export interface UserCellProps {
|
||||
Avatar: UserAvatarProps
|
||||
/**
|
||||
* primaryText is rendered beside the avatar
|
||||
*/
|
||||
primaryText: string /* | React.ReactNode <-- if needed */
|
||||
/**
|
||||
* caption is rendered beneath the avatar and primaryText
|
||||
*/
|
||||
caption?: string /* | React.ReactNode <-- if needed */
|
||||
/**
|
||||
* onPrimaryTextSelect, if defined, is called when the primaryText is clicked
|
||||
*/
|
||||
onPrimaryTextSelect?: () => void
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme) => ({
|
||||
primaryText: {
|
||||
color: theme.palette.text.primary,
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
fontSize: "16px",
|
||||
lineHeight: "15px",
|
||||
marginBottom: "5px",
|
||||
},
|
||||
}))
|
||||
|
||||
/**
|
||||
* UserCell is a single cell in an audit log table row that contains user-level
|
||||
* information
|
||||
*/
|
||||
export const UserCell: FC<React.PropsWithChildren<UserCellProps>> = ({
|
||||
Avatar,
|
||||
caption,
|
||||
primaryText,
|
||||
onPrimaryTextSelect,
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
|
||||
return (
|
||||
<Box alignItems="center" display="flex" flexDirection="row">
|
||||
<Box display="flex" margin="auto 14px auto 0">
|
||||
<UserAvatar {...Avatar} />
|
||||
</Box>
|
||||
|
||||
<Box display="flex" flexDirection="column">
|
||||
{onPrimaryTextSelect ? (
|
||||
<Link className={styles.primaryText} onClick={onPrimaryTextSelect}>
|
||||
{primaryText}
|
||||
</Link>
|
||||
) : (
|
||||
<Typography className={styles.primaryText}>{primaryText}</Typography>
|
||||
)}
|
||||
|
||||
{caption && (
|
||||
<Typography color="textSecondary" variant="caption">
|
||||
{caption}
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
import { fireEvent, screen } from "@testing-library/react"
|
||||
import userEvent from "@testing-library/user-event"
|
||||
import { rest } from "msw"
|
||||
import { Route, Routes } from "react-router-dom"
|
||||
import { createMemoryRouter } from "react-router-dom"
|
||||
import { Language } from "../../components/SignInForm/SignInForm"
|
||||
import {
|
||||
history,
|
||||
render,
|
||||
renderWithRouter,
|
||||
waitForLoaderToBeRemoved,
|
||||
} from "../../testHelpers/renderHelpers"
|
||||
import { server } from "../../testHelpers/server"
|
||||
@@ -17,7 +17,6 @@ const { t } = i18n
|
||||
|
||||
describe("LoginPage", () => {
|
||||
beforeEach(() => {
|
||||
history.replace("/login")
|
||||
// appear logged out
|
||||
server.use(
|
||||
rest.get("/api/v2/users/me", (req, res, ctx) => {
|
||||
@@ -58,7 +57,6 @@ describe("LoginPage", () => {
|
||||
// Then
|
||||
const errorMessage = await screen.findByText(apiErrorMessage)
|
||||
expect(errorMessage).toBeDefined()
|
||||
expect(history.location.pathname).toEqual("/login")
|
||||
})
|
||||
|
||||
it("shows github authentication when enabled", async () => {
|
||||
@@ -92,11 +90,20 @@ describe("LoginPage", () => {
|
||||
)
|
||||
|
||||
// When
|
||||
render(
|
||||
<Routes>
|
||||
<Route path="/login" element={<LoginPage />}></Route>
|
||||
<Route path="/setup" element={<h1>Setup</h1>}></Route>
|
||||
</Routes>,
|
||||
renderWithRouter(
|
||||
createMemoryRouter(
|
||||
[
|
||||
{
|
||||
path: "/login",
|
||||
element: <LoginPage />,
|
||||
},
|
||||
{
|
||||
path: "/setup",
|
||||
element: <h1>Setup</h1>,
|
||||
},
|
||||
],
|
||||
{ initialEntries: ["/login"] },
|
||||
),
|
||||
)
|
||||
|
||||
// Then
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { fireEvent, screen, waitFor } from "@testing-library/react"
|
||||
import userEvent from "@testing-library/user-event"
|
||||
import { rest } from "msw"
|
||||
import { history, render } from "testHelpers/renderHelpers"
|
||||
import { render } from "testHelpers/renderHelpers"
|
||||
import { server } from "testHelpers/server"
|
||||
import { SetupPage } from "./SetupPage"
|
||||
import { Language as PageViewLanguage } from "./SetupPageView"
|
||||
@@ -30,7 +30,6 @@ const fillForm = async ({
|
||||
|
||||
describe("Setup Page", () => {
|
||||
beforeEach(() => {
|
||||
history.replace("/setup")
|
||||
// appear logged out
|
||||
server.use(
|
||||
rest.get("/api/v2/users/me", (req, res, ctx) => {
|
||||
|
||||
@@ -4,7 +4,6 @@ import { rest } from "msw"
|
||||
import { Language as FormLanguage } from "../../../components/CreateUserForm/CreateUserForm"
|
||||
import { Language as FooterLanguage } from "../../../components/FormFooter/FormFooter"
|
||||
import {
|
||||
history,
|
||||
renderWithAuth,
|
||||
waitForLoaderToBeRemoved,
|
||||
} from "../../../testHelpers/renderHelpers"
|
||||
@@ -41,10 +40,6 @@ const fillForm = async ({
|
||||
}
|
||||
|
||||
describe("Create User Page", () => {
|
||||
beforeEach(() => {
|
||||
history.replace("/users/create")
|
||||
})
|
||||
|
||||
it("shows validation error message", async () => {
|
||||
await renderCreateUserPage()
|
||||
await fillForm({ email: "test" })
|
||||
|
||||
@@ -25,7 +25,7 @@ describe("WorkspaceBuildPage", () => {
|
||||
client.onmessage = async () => {
|
||||
renderWithAuth(<WorkspaceBuildPage />, {
|
||||
route: `/@${MockWorkspace.owner_name}/${MockWorkspace.name}/builds/${MockWorkspace.latest_build.build_number}`,
|
||||
path: "/@:username/:workspace/builds/:buildNumber",
|
||||
path: "/:username/:workspace/builds/:buildNumber",
|
||||
})
|
||||
|
||||
await screen.findByText(MockWorkspaceBuild.workspace_name)
|
||||
|
||||
@@ -45,7 +45,7 @@ const renderWorkspacePage = async () => {
|
||||
})
|
||||
renderWithAuth(<WorkspacePage />, {
|
||||
route: `/@${MockWorkspace.owner_name}/${MockWorkspace.name}`,
|
||||
path: "/@:username/:workspace",
|
||||
path: "/:username/:workspace",
|
||||
})
|
||||
|
||||
await waitForLoaderToBeRemoved()
|
||||
|
||||
@@ -33,10 +33,12 @@ const useFailedBuildLogs = (workspace: Workspace | undefined) => {
|
||||
}
|
||||
|
||||
export const WorkspacePage: FC = () => {
|
||||
const { username, workspace: workspaceName } = useParams() as {
|
||||
const params = useParams() as {
|
||||
username: string
|
||||
workspace: string
|
||||
}
|
||||
const workspaceName = params.workspace
|
||||
const username = params.username.replace("@", "")
|
||||
const orgId = useOrganizationId()
|
||||
const [workspaceState, workspaceSend] = useMachine(workspaceMachine, {
|
||||
context: {
|
||||
|
||||
+2
-2
@@ -40,9 +40,9 @@ test("Submit the workspace settings page successfully", async () => {
|
||||
const user = userEvent.setup()
|
||||
renderWithWorkspaceSettingsLayout(<WorkspaceParametersPage />, {
|
||||
route: "/@test-user/test-workspace/settings",
|
||||
path: "/@:username/:workspace/settings",
|
||||
path: "/:username/:workspace/settings",
|
||||
// Need this because after submit the user is redirected
|
||||
extraRoutes: [{ path: "/@:username/:workspace", element: <div /> }],
|
||||
extraRoutes: [{ path: "/:username/:workspace", element: <div /> }],
|
||||
})
|
||||
await waitForLoaderToBeRemoved()
|
||||
// Fill the form and submit
|
||||
|
||||
+38
-35
@@ -258,11 +258,44 @@ describe("WorkspaceSchedulePage", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("autostop", () => {
|
||||
it("uses template default ttl when first enabled", async () => {
|
||||
// have autostop disabled
|
||||
server.use(
|
||||
rest.get(
|
||||
"/api/v2/users/:userId/workspace/:workspaceName",
|
||||
(req, res, ctx) => {
|
||||
return res(
|
||||
ctx.status(200),
|
||||
ctx.json({ ...MockWorkspace, ttl_ms: 0 }),
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
renderWithWorkspaceSettingsLayout(<WorkspaceSchedulePage />, {
|
||||
route: `/@${MockUser.username}/${MockWorkspace.name}/schedule`,
|
||||
path: "/:username/:workspace/schedule",
|
||||
})
|
||||
const user = userEvent.setup()
|
||||
const autostopToggle = await screen.findByLabelText(
|
||||
FormLanguage.stopSwitch,
|
||||
)
|
||||
// enable autostop
|
||||
await user.click(autostopToggle)
|
||||
// find helper text that describes the mock template's 24 hour default
|
||||
const autostopHelperText = await screen.findByText(
|
||||
"Your workspace will shut down a day after",
|
||||
{ exact: false },
|
||||
)
|
||||
expect(autostopHelperText).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe("autostop change dialog", () => {
|
||||
it("shows if autostop is changed", async () => {
|
||||
renderWithWorkspaceSettingsLayout(<WorkspaceSchedulePage />, {
|
||||
route: `/@${MockUser.username}/${MockWorkspace.name}/schedule`,
|
||||
path: "/@:username/:workspace/schedule",
|
||||
path: "/:username/:workspace/schedule",
|
||||
})
|
||||
const user = userEvent.setup()
|
||||
const autostopToggle = await screen.findByLabelText(
|
||||
@@ -281,7 +314,10 @@ describe("WorkspaceSchedulePage", () => {
|
||||
it("doesn't show if autostop is not changed", async () => {
|
||||
renderWithWorkspaceSettingsLayout(<WorkspaceSchedulePage />, {
|
||||
route: `/@${MockUser.username}/${MockWorkspace.name}/schedule`,
|
||||
path: "/@:username/:workspace/schedule",
|
||||
path: "/:username/:workspace/schedule",
|
||||
extraRoutes: [
|
||||
{ path: "/:username/:workspace", element: <div>Workspace</div> },
|
||||
],
|
||||
})
|
||||
const user = userEvent.setup()
|
||||
const autostartToggle = await screen.findByLabelText(
|
||||
@@ -297,37 +333,4 @@ describe("WorkspaceSchedulePage", () => {
|
||||
expect(dialog).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe("autostop", () => {
|
||||
it("uses template default ttl when first enabled", async () => {
|
||||
// have autostop disabled
|
||||
server.use(
|
||||
rest.get(
|
||||
"/api/v2/users/:userId/workspace/:workspaceName",
|
||||
(req, res, ctx) => {
|
||||
return res(
|
||||
ctx.status(200),
|
||||
ctx.json({ ...MockWorkspace, ttl_ms: 0 }),
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
renderWithWorkspaceSettingsLayout(<WorkspaceSchedulePage />, {
|
||||
route: `/@${MockUser.username}/${MockWorkspace.name}/schedule`,
|
||||
path: "/@:username/:workspace/schedule",
|
||||
})
|
||||
const user = userEvent.setup()
|
||||
const autostopToggle = await screen.findByLabelText(
|
||||
FormLanguage.stopSwitch,
|
||||
)
|
||||
// enable autostop
|
||||
await user.click(autostopToggle)
|
||||
// find helper text that describes the mock template's 24 hour default
|
||||
const autostopHelperText = await screen.findByText(
|
||||
"Your workspace will shut down a day after",
|
||||
{ exact: false },
|
||||
)
|
||||
expect(autostopHelperText).toBeDefined()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+3
-5
@@ -16,7 +16,6 @@ import { pageTitle } from "utils/page"
|
||||
import { scheduleChanged } from "utils/schedule"
|
||||
import * as TypesGen from "../../../api/typesGenerated"
|
||||
import { WorkspaceScheduleForm } from "../../../components/WorkspaceScheduleForm/WorkspaceScheduleForm"
|
||||
import { firstOrItem } from "../../../utils/array"
|
||||
import { workspaceSchedule } from "../../../xServices/workspaceSchedule/workspaceScheduleXService"
|
||||
import {
|
||||
formValuesToAutostartRequest,
|
||||
@@ -41,11 +40,10 @@ const useStyles = makeStyles((theme) => ({
|
||||
export const WorkspaceSchedulePage: FC = () => {
|
||||
const { t } = useTranslation("workspaceSchedulePage")
|
||||
const styles = useStyles()
|
||||
const { username: usernameQueryParam, workspace: workspaceQueryParam } =
|
||||
useParams()
|
||||
const params = useParams() as { username: string; workspace: string }
|
||||
const navigate = useNavigate()
|
||||
const username = firstOrItem(usernameQueryParam, null)
|
||||
const workspaceName = firstOrItem(workspaceQueryParam, null)
|
||||
const username = params.username.replace("@", "")
|
||||
const workspaceName = params.workspace
|
||||
const { workspace } = useWorkspaceSettingsContext()
|
||||
const [scheduleState, scheduleSend] = useMachine(workspaceSchedule, {
|
||||
context: { workspace },
|
||||
|
||||
@@ -43,10 +43,12 @@ export const useWorkspaceSettingsContext = () => {
|
||||
|
||||
export const WorkspaceSettingsLayout: FC = () => {
|
||||
const styles = useStyles()
|
||||
const { workspace: workspaceName, username } = useParams() as {
|
||||
const params = useParams() as {
|
||||
workspace: string
|
||||
username: string
|
||||
}
|
||||
const workspaceName = params.workspace
|
||||
const username = params.username.replace("@", "")
|
||||
const { data: settings } = useWorkspace(username, workspaceName)
|
||||
|
||||
return (
|
||||
|
||||
@@ -21,9 +21,9 @@ test("Submit the workspace settings page successfully", async () => {
|
||||
const user = userEvent.setup()
|
||||
renderWithWorkspaceSettingsLayout(<WorkspaceSettingsPage />, {
|
||||
route: "/@test-user/test-workspace/settings",
|
||||
path: "/@:username/:workspace/settings",
|
||||
path: "/:username/:workspace/settings",
|
||||
// Need this because after submit the user is redirected
|
||||
extraRoutes: [{ path: "/@:username/:workspace", element: <div /> }],
|
||||
extraRoutes: [{ path: "/:username/:workspace", element: <div /> }],
|
||||
})
|
||||
await waitForLoaderToBeRemoved()
|
||||
// Fill the form and submit
|
||||
|
||||
@@ -9,10 +9,12 @@ import { patchWorkspace } from "api/api"
|
||||
import { WorkspaceSettingsFormValues } from "./WorkspaceSettingsForm"
|
||||
|
||||
const WorkspaceSettingsPage = () => {
|
||||
const { username, workspace: workspaceName } = useParams() as {
|
||||
username: string
|
||||
const params = useParams() as {
|
||||
workspace: string
|
||||
username: string
|
||||
}
|
||||
const workspaceName = params.workspace
|
||||
const username = params.username.replace("@", "")
|
||||
const { workspace } = useWorkspaceSettingsContext()
|
||||
const navigate = useNavigate()
|
||||
const mutation = useMutation({
|
||||
|
||||
@@ -2,7 +2,7 @@ import { screen } from "@testing-library/react"
|
||||
import { rest } from "msw"
|
||||
import * as CreateDayString from "utils/createDayString"
|
||||
import { MockWorkspace, MockWorkspacesResponse } from "testHelpers/entities"
|
||||
import { history, renderWithAuth } from "testHelpers/renderHelpers"
|
||||
import { renderWithAuth } from "testHelpers/renderHelpers"
|
||||
import { server } from "testHelpers/server"
|
||||
import WorkspacesPage from "./WorkspacesPage"
|
||||
import { i18n } from "i18n"
|
||||
@@ -11,7 +11,6 @@ const { t } = i18n
|
||||
|
||||
describe("WorkspacesPage", () => {
|
||||
beforeEach(() => {
|
||||
history.replace("/workspaces")
|
||||
// Mocking the dayjs module within the createDayString file
|
||||
const mock = jest.spyOn(CreateDayString, "createDayString")
|
||||
mock.mockImplementation(() => "a minute ago")
|
||||
|
||||
@@ -1,40 +1,52 @@
|
||||
import {
|
||||
render as wrappedRender,
|
||||
RenderResult,
|
||||
render as tlRender,
|
||||
screen,
|
||||
waitForElementToBeRemoved,
|
||||
} from "@testing-library/react"
|
||||
import { AppProviders } from "app"
|
||||
import { DashboardLayout } from "components/Dashboard/DashboardLayout"
|
||||
import { createMemoryHistory } from "history"
|
||||
import { i18n } from "i18n"
|
||||
import { TemplateSettingsLayout } from "pages/TemplateSettingsPage/TemplateSettingsLayout"
|
||||
import { WorkspaceSettingsLayout } from "pages/WorkspaceSettingsPage/WorkspaceSettingsLayout"
|
||||
import { FC, ReactElement } from "react"
|
||||
import { I18nextProvider } from "react-i18next"
|
||||
import {
|
||||
unstable_HistoryRouter as HistoryRouter,
|
||||
RouterProvider,
|
||||
createMemoryRouter,
|
||||
RouteObject,
|
||||
} from "react-router-dom"
|
||||
import { RequireAuth } from "../components/RequireAuth/RequireAuth"
|
||||
import { MockUser } from "./entities"
|
||||
import { ReactNode } from "react"
|
||||
|
||||
export const history = createMemoryHistory()
|
||||
|
||||
export const WrapperComponent: FC<React.PropsWithChildren<unknown>> = ({
|
||||
children,
|
||||
}) => {
|
||||
return (
|
||||
<AppProviders>
|
||||
<HistoryRouter history={history}>{children}</HistoryRouter>
|
||||
</AppProviders>
|
||||
const baseRender = (element: ReactNode) => {
|
||||
return tlRender(
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<AppProviders>{element}</AppProviders>
|
||||
</I18nextProvider>,
|
||||
)
|
||||
}
|
||||
|
||||
export const render = (component: ReactElement): RenderResult => {
|
||||
return wrappedRender(<WrapperComponent>{component}</WrapperComponent>)
|
||||
export const renderWithRouter = (
|
||||
router: ReturnType<typeof createMemoryRouter>,
|
||||
) => {
|
||||
return {
|
||||
...baseRender(<RouterProvider router={router} />),
|
||||
router,
|
||||
}
|
||||
}
|
||||
|
||||
export const render = (element: ReactNode) => {
|
||||
return renderWithRouter(
|
||||
createMemoryRouter(
|
||||
[
|
||||
{
|
||||
path: "/",
|
||||
element,
|
||||
},
|
||||
],
|
||||
{ initialEntries: ["/"] },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
type RenderWithAuthOptions = {
|
||||
@@ -69,19 +81,12 @@ export function renderWithAuth(
|
||||
...nonAuthenticatedRoutes,
|
||||
]
|
||||
|
||||
const router = createMemoryRouter(routes, { initialEntries: [route] })
|
||||
|
||||
const renderResult = wrappedRender(
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<AppProviders>
|
||||
<RouterProvider router={router} />
|
||||
</AppProviders>
|
||||
</I18nextProvider>,
|
||||
const renderResult = renderWithRouter(
|
||||
createMemoryRouter(routes, { initialEntries: [route] }),
|
||||
)
|
||||
|
||||
return {
|
||||
user: MockUser,
|
||||
router,
|
||||
...renderResult,
|
||||
}
|
||||
}
|
||||
@@ -113,19 +118,12 @@ export function renderWithTemplateSettingsLayout(
|
||||
...nonAuthenticatedRoutes,
|
||||
]
|
||||
|
||||
const router = createMemoryRouter(routes, { initialEntries: [route] })
|
||||
|
||||
const renderResult = wrappedRender(
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<AppProviders>
|
||||
<RouterProvider router={router} />
|
||||
</AppProviders>
|
||||
</I18nextProvider>,
|
||||
const renderResult = renderWithRouter(
|
||||
createMemoryRouter(routes, { initialEntries: [route] }),
|
||||
)
|
||||
|
||||
return {
|
||||
user: MockUser,
|
||||
router,
|
||||
...renderResult,
|
||||
}
|
||||
}
|
||||
@@ -148,7 +146,7 @@ export function renderWithWorkspaceSettingsLayout(
|
||||
children: [
|
||||
{
|
||||
element: <WorkspaceSettingsLayout />,
|
||||
children: [{ path, element }, ...extraRoutes],
|
||||
children: [{ element, path }, ...extraRoutes],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -157,19 +155,12 @@ export function renderWithWorkspaceSettingsLayout(
|
||||
...nonAuthenticatedRoutes,
|
||||
]
|
||||
|
||||
const router = createMemoryRouter(routes, { initialEntries: [route] })
|
||||
|
||||
const renderResult = wrappedRender(
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<AppProviders>
|
||||
<RouterProvider router={router} />
|
||||
</AppProviders>
|
||||
</I18nextProvider>,
|
||||
const renderResult = renderWithRouter(
|
||||
createMemoryRouter(routes, { initialEntries: [route] }),
|
||||
)
|
||||
|
||||
return {
|
||||
user: MockUser,
|
||||
router,
|
||||
...renderResult,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { firstOrItem } from "./array"
|
||||
|
||||
describe("array", () => {
|
||||
describe("firstOrItem", () => {
|
||||
it("returns null if empty array", () => {
|
||||
expect(firstOrItem([], null)).toBeNull()
|
||||
})
|
||||
|
||||
it("returns first item if array with more one item", () => {
|
||||
expect(firstOrItem(["a", "b"], "c")).toEqual("a")
|
||||
})
|
||||
|
||||
it("returns item if single item", () => {
|
||||
expect(firstOrItem("c", "d")).toEqual("c")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Helper function that, given an array or a single item:
|
||||
* - If an array with no elements, returns null
|
||||
* - If an array with 1 or more elements, returns the first element
|
||||
* - If a single item, returns that item
|
||||
*/
|
||||
export const firstOrItem = <T>(
|
||||
itemOrItems: undefined | T | T[],
|
||||
defaults: T,
|
||||
): T => {
|
||||
if (Array.isArray(itemOrItems)) {
|
||||
return itemOrItems.length > 0 ? itemOrItems[0] : defaults
|
||||
}
|
||||
|
||||
if (typeof itemOrItems === "undefined") {
|
||||
return defaults
|
||||
}
|
||||
|
||||
return itemOrItems
|
||||
}
|
||||
Reference in New Issue
Block a user