Skip to content

Commit

Permalink
wip oidc in wrappedRender and add cardTab style
Browse files Browse the repository at this point in the history
  • Loading branch information
RenauxLeaInsee committed May 3, 2024
1 parent 405edbb commit b2dbe37
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 65 deletions.
26 changes: 21 additions & 5 deletions src/WrappedRender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,31 @@ import { messagesFr } from "./i18n-fr";
import { IntlProvider } from "react-intl";
import { ReactElement } from "react";
import { SonorTheme } from "./theme";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { AuthProvider } from "./hooks/useAuth";

const router = createBrowserRouter(routes);

const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000,
refetchOnWindowFocus: false,
retry: false,
},
},
});

export const WrappedRender = (children: ReactElement) => {
return render(
<SonorTheme>
<IntlProvider locale="fr" messages={messagesFr}>
<Router {...router}>{children}</Router>
</IntlProvider>
</SonorTheme>,
<AuthProvider>
<QueryClientProvider client={queryClient}>
<SonorTheme>
<IntlProvider locale="fr" messages={messagesFr}>
<Router {...router}>{children}</Router>
</IntlProvider>
</SonorTheme>
</QueryClientProvider>
</AuthProvider>,
);
};
19 changes: 18 additions & 1 deletion src/functions/api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import type { APIPaths, APIRequests, APIResponse } from "../types/api.ts";
import type { APIPaths, APIRequests, APIResponse, APIMethods, APIRequest } from "../types/api.ts";

const baseURL = import.meta.env.VITE_API_ENDPOINT;

const mockApiRequest = new Map<string, (url: string, options: any) => any>()

export function mockRequest<
Path extends APIPaths,
Method extends APIMethods<Path>,
>(path: Path, method: Method, cb: (options: APIRequest<Path, Method>) => APIResponse<Path, Method>) {
mockApiRequest.set(`${method} ${path}`, cb as any)
}

export function clearMockRequest() {
mockApiRequest.clear()
}

export async function fetchAPI<
Path extends APIPaths,
Options extends APIRequests<Path> & { signal?: AbortSignal; headers?: Record<string, string> },
Expand Down Expand Up @@ -46,6 +59,10 @@ export async function fetchAPI<
}
}
}
const requestKey = `${fetchOptions.method?.toLowerCase()} ${path}`
if (mockApiRequest.has(requestKey)) {
return (mockApiRequest.get('requestKey') as any)(options) as APIResponse<Path, Options["method"]>
}
const response = await fetch(url.toString(), fetchOptions);
if (response.status === 204) {
return null as any;
Expand Down
3 changes: 2 additions & 1 deletion src/functions/oidc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export const createAppOidc = () => {
if (isOidc) {
return !import.meta.env.VITE_OIDC_ISSUER
? createMockReactOidc<TokenInfo>({
isUserInitiallyLoggedIn: false,
isUserInitiallyLoggedIn: true,

mockedTokens: {
decodedIdToken: {
inseegroupedefaut: ["gr"],
Expand Down
19 changes: 9 additions & 10 deletions src/pages/FollowCampaignPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ enum Tab {

export const FollowCampaignPage = () => {
const intl = useIntl();
const [currentTab, setCurrentTab] = useState(Tab.progress);
const handleChange = (_: SyntheticEvent, newValue: Tab) => {
const [currentTab, setCurrentTab] = useState<string>(Tab.progress);
const handleChange = (_: SyntheticEvent, newValue: string) => {
setCurrentTab(newValue);
};

Expand All @@ -33,19 +33,18 @@ export const FollowCampaignPage = () => {

return (
<>
<FollowSinglePageHeader category={"survey"} label={labelMock} breadcrumbs={breadcrumbs} />
<Tabs
value={currentTab}
<FollowSinglePageHeader
category={"survey"}
label={labelMock}
breadcrumbs={breadcrumbs}
currentTab={currentTab}
onChange={handleChange}
sx={{
px: 3,
backgroundColor: "white",
}}
>
{Object.keys(Tab).map(k => (
<PageTab key={k} value={k} label={intl.formatMessage({ id: k })} />
))}
</Tabs>
</FollowSinglePageHeader>

<Stack px={3} py={4}>
{currentTab === Tab.progress && <FollowCampaignProgress />}
{currentTab === Tab.collect && <>tab collecte</>}
Expand Down
19 changes: 9 additions & 10 deletions src/pages/FollowInterviewerPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const FollowInterviewerPage = () => {
const { id } = useParams();
const intl = useIntl();

const [currentTab, setCurrentTab] = useState(Tab.progress);
const [currentTab, setCurrentTab] = useState<string>(Tab.progress);

const { data: interviewer } = useFetchQuery("/api/interviewer/{id}", {
urlParams: {
Expand All @@ -35,7 +35,7 @@ export const FollowInterviewerPage = () => {

const label = `${interviewer.lastName?.toLocaleUpperCase() ?? ""} ${interviewer.firstName ?? ""}`;

const handleChange = (_: SyntheticEvent, newValue: Tab) => {
const handleChange = (_: SyntheticEvent, newValue: string) => {
setCurrentTab(newValue);
};

Expand All @@ -47,19 +47,18 @@ export const FollowInterviewerPage = () => {

return (
<>
<FollowSinglePageHeader category={"interviewer"} label={label} breadcrumbs={breadcrumbs} />
<Tabs
value={currentTab}
<FollowSinglePageHeader
category={"interviewer"}
label={label}
breadcrumbs={breadcrumbs}
currentTab={currentTab}
onChange={handleChange}
sx={{
px: 3,
backgroundColor: "white",
}}
>
{Object.keys(Tab).map(k => (
<PageTab key={k} value={k} label={intl.formatMessage({ id: k })} />
))}
</Tabs>
</FollowSinglePageHeader>

<Stack px={3} py={4}>
{currentTab === Tab.progress && <>tab avancement</>}
{currentTab === Tab.collect && <>tab collecte</>}
Expand Down
17 changes: 6 additions & 11 deletions src/pages/FollowOrganizationUnitPage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SyntheticEvent, useState } from "react";
import { useIntl } from "react-intl";
import { FollowSinglePageHeader } from "../ui/follow/FollowSinglePageHeader";
import Tabs from "@mui/material/Tabs";

import { PageTab } from "../ui/PageTab";
import Stack from "@mui/material/Stack";

Expand All @@ -15,8 +15,8 @@ enum Tab {

export const FollowOrganizationUnitPage = () => {
const intl = useIntl();
const [currentTab, setCurrentTab] = useState(Tab.progress);
const handleChange = (_: SyntheticEvent, newValue: Tab) => {
const [currentTab, setCurrentTab] = useState<string>(Tab.progress);
const handleChange = (_: SyntheticEvent, newValue: string) => {
setCurrentTab(newValue);
};

Expand All @@ -32,19 +32,14 @@ export const FollowOrganizationUnitPage = () => {
category={"organizationUnit"}
label={labelMock}
breadcrumbs={breadcrumbs}
/>
<Tabs
value={currentTab}
currentTab={currentTab}
onChange={handleChange}
sx={{
px: 3,
backgroundColor: "white",
}}
>
{Object.keys(Tab).map(k => (
<PageTab key={k} value={k} label={intl.formatMessage({ id: k })} />
))}
</Tabs>
</FollowSinglePageHeader>

<Stack px={3} py={4}>
{currentTab === Tab.progress && <>tab avancement</>}
{currentTab === Tab.collect && <>tab collecte</>}
Expand Down
54 changes: 30 additions & 24 deletions src/theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -328,36 +328,42 @@ export const theme = createTheme({
{
props: { classes: "cardTab" },
style: {
borderTopLeftRadius: "16px !important",
borderTopRightRadius: "16px !important",
paddingLeft: 40,
paddingRight: 40,
padding: "10px 40px",
backgroundColor: "#EFEFEF",
border: "none",
...typography.titleSmall,
textTransform: "none",
"&:hover": {
backgroundColor: "#EFEFEF",
},
":nth-of-type(2)": {
left: -20,
},
":nth-of-type(3)": {
left: -40,
},
":nth-of-type(4)": {
left: -60,
},
":nth-of-type(5)": {
left: -80,
},
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
zIndex: 1,
overflow: "visible",

"&.Mui-selected": {
position: "relative",
zIndex: 2,
zIndex: 3,
background: "white",
"&:hover": {
background: "white",
},

"&::before": {
content: "''",
position: "absolute",
bottom: 0,
width: 15,
height: 15,
background:
"#FFF radial-gradient(circle at top left, #EFEFEF 0px, #EFEFEF 70%, transparent 71%, transparent 100%) no-repeat",
left: -15,
zIndex: 5,
},
"&::after": {
content: "''",
position: "absolute",
bottom: 0,
width: 15,
height: 15,
background:
"#FFF radial-gradient(circle at top right, #EFEFEF 0px, #EFEFEF 70%, transparent 71%, transparent 100%) no-repeat",
right: -15,
zIndex: 5,
},
},
},
},
Expand Down
7 changes: 6 additions & 1 deletion src/ui/follow/FollowCampaignProgress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@ export const FollowCampaignProgress = () => {
<Tabs
value={currentTab}
onChange={handleChange}
sx={{ ml: 5, ".MuiTabs-indicator": { backgroundColor: "white" } }}
sx={{
ml: 5,
".MuiTabs-indicator": { backgroundColor: "white" },
position: "relative",
width: "fit-content",
}}
>
{Object.keys(Tab).map(k => (
<MuiTab classes={"cardTab"} label={intl.formatMessage({ id: k })} key={k} value={k} />
Expand Down
55 changes: 55 additions & 0 deletions src/ui/follow/FollowOrganizationUnitCard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import userEvent from "@testing-library/user-event";
import { WrappedRender } from "../../WrappedRender";
import { FollowOrganizationUnitCard } from "./FollowOrganizationUnitCard";
import { act, screen, waitFor } from "@testing-library/react";
import { clearMockRequest, mockRequest } from "../../functions/api";

describe("FollowOrganizationUnitCard component", () => {
beforeEach(() => {
vi.resetModules();
vi.clearAllMocks();
mockRequest("/api/organization-units", "get", () => [
{
id: "DR75",
label: "Ile de France",
type: "LOCAL" as const,
users: [],
},
{
id: "DR51",
label: "Champagne-Ardenne",
type: "LOCAL" as const,
users: [],
},
]);
});

afterEach(() => clearMockRequest());

it("should render FollowOrganizationUnitCard component", () => {
WrappedRender(<FollowOrganizationUnitCard />);

expect(screen.getByText("Suivre un site")).toBeInTheDocument();
expect(screen.getByRole("textbox")).toBeInTheDocument();
expect(screen.getByText("Champagne-Ardenne")).toBeInTheDocument();

expect(screen.getByText("Ile de France")).toBeInTheDocument();
});

it("should display search result", async () => {
await act(async () => WrappedRender(<FollowOrganizationUnitCard />));

userEvent.type(screen.getByRole("textbox"), "france");

expect(screen.getByText("Ile de France")).toBeInTheDocument();
await waitFor(() => expect(screen.queryByText("Champagne-Ardenne")).not.toBeInTheDocument());
});

it("should display sorted OU", async () => {
await act(async () => WrappedRender(<FollowOrganizationUnitCard />));

const links = screen.getAllByRole("link");
expect(links[0]).toContainHTML("Champagne-Ardenne");
expect(links[1]).toContainHTML("Ile de France");
});
});
24 changes: 22 additions & 2 deletions src/ui/follow/FollowSinglePageHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
import { useNavigate } from "react-router-dom";
import { Row } from "../Row";
import Stack from "@mui/material/Stack";
import { Box, Divider, IconButton, Typography } from "@mui/material";
import { Box, Divider, IconButton, Tabs, Typography } from "@mui/material";
import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew";
import { Breadcrumbs, BreadcrumbsItem } from "../Breadcrumbs";
import { useIntl } from "react-intl";
import { ReactNode, SyntheticEvent } from "react";

type Props = {
category: string;
label: string;
breadcrumbs: BreadcrumbsItem[];
currentTab: string;
onChange: (_: SyntheticEvent, newValue: string) => void;
children: ReactNode;
};

export const FollowSinglePageHeader = ({ category, label, breadcrumbs }: Props) => {
export const FollowSinglePageHeader = ({
category,
label,
breadcrumbs,
currentTab,
onChange,
children,
}: Props) => {
const navigate = useNavigate();
const intl = useIntl();

Expand All @@ -34,6 +45,15 @@ export const FollowSinglePageHeader = ({ category, label, breadcrumbs }: Props)
<Breadcrumbs items={breadcrumbs} />
</Row>
<Divider variant="fullWidth" />
<Tabs
value={currentTab}
onChange={onChange}
sx={{
px: 3,
}}
>
{children}
</Tabs>
</Stack>
);
};

0 comments on commit b2dbe37

Please sign in to comment.