Skip to content

Commit

Permalink
Merge branch '3.2.0' into CRDCDH-2266
Browse files Browse the repository at this point in the history
  • Loading branch information
Alejandro-Vega authored Jan 30, 2025
2 parents bd3acc2 + 5e508a3 commit 8e06ec7
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 13 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/components/StatusBar/components/HistorySection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const HistorySection: FC = () => {
placement="top"
open={undefined}
disableHoverListener={false}
disableInteractive
arrow
>
<Stack direction="row" alignItems="center" data-testid="status-bar-pending-conditions">
Expand All @@ -103,6 +104,7 @@ const HistorySection: FC = () => {
placement="top"
open={undefined}
disableHoverListener={false}
disableInteractive
arrow
>
<span>{children}</span>
Expand Down
2 changes: 1 addition & 1 deletion src/content/dataSubmissions/DataSubmissionsListView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ const ListingView: FC = () => {
defaultOrder="desc"
disableUrlParams={false}
position="bottom"
noContentText="There are no data submissions associated with your account"
noContentText="You either do not have the appropriate permissions to view data submissions, or there are no data submissions associated with your account."
onFetchData={handleFetchData}
containerProps={{
sx: {
Expand Down
125 changes: 125 additions & 0 deletions src/content/organizations/Controller.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import React, { FC, useMemo } from "react";
import { render, waitFor } from "@testing-library/react";
import { MemoryRouter, Routes, Route } from "react-router-dom";
import {
Context as AuthContext,
ContextState as AuthContextState,
Status as AuthContextStatus,
} from "../../components/Contexts/AuthContext";
import OrganizationController from "./Controller";

jest.mock("../../components/Contexts/OrganizationListContext", () => ({
__esModule: true,
OrganizationProvider: ({ children }: { children: React.ReactNode }) => (
<div data-testid="organization-provider">{children}</div>
),
}));

jest.mock("./ListView", () => ({
__esModule: true,
default: () => <div data-testid="organization-list">MOCK-LIST-PAGE</div>,
}));

jest.mock("./OrganizationView", () => ({
__esModule: true,
default: ({ _id }) => <div data-testid="organization-view">MOCK-EDIT-PAGE {_id}</div>,
}));

const baseUser: Omit<User, "permissions"> = {
_id: "",
role: "fake role" as UserRole, // NOTE: This component does not depend on the role
firstName: "",
lastName: "",
userStatus: "Active",
IDP: "nih",
email: "",
dataCommons: [],
createdAt: "",
updateAt: "",
studies: null,
notifications: [],
};

type ParentProps = {
permissions?: AuthPermissions[];
initialEntry?: string;
ctxStatus?: AuthContextStatus;
children: React.ReactNode;
};

const TestParent: FC<ParentProps> = ({
permissions = ["program:manage"],
initialEntry = "/programs",
ctxStatus = AuthContextStatus.LOADED,
children,
}: ParentProps) => {
const baseAuthCtx: AuthContextState = useMemo<AuthContextState>(
() => ({
status: ctxStatus,
isLoggedIn: true,
user: { ...baseUser, permissions },
}),
[ctxStatus, permissions]
);

return (
<AuthContext.Provider value={baseAuthCtx}>
<MemoryRouter initialEntries={[initialEntry]}>
<Routes>
<Route path="/programs/:orgId?" element={children} />
<Route path="/" element={<div>Root Page</div>} />
</Routes>
</MemoryRouter>
</AuthContext.Provider>
);
};

describe("Basic Functionality", () => {
it("should render the page without crashing", async () => {
expect(() =>
render(<OrganizationController />, {
wrapper: ({ children }) => <TestParent>{children}</TestParent>,
})
).not.toThrow();
});

it("should show a loading spinner when the AuthCtx is loading", async () => {
const { getByTestId } = render(<OrganizationController />, {
wrapper: ({ children }) => (
<TestParent ctxStatus={AuthContextStatus.LOADING}>{children}</TestParent>
),
});

expect(getByTestId("organization-suspense-loader")).toBeInTheDocument();
});

it("should redirect the user missing the required permissions to the home page", async () => {
const { getByText } = render(<OrganizationController />, {
wrapper: ({ children }) => <TestParent permissions={[]}>{children}</TestParent>,
});

expect(getByText("Root Page")).toBeInTheDocument();
});

it("should render the OrganizationView when a orgId param is provided", async () => {
const { getByText } = render(<OrganizationController />, {
wrapper: ({ children }) => (
<TestParent initialEntry="/programs/program-123">{children}</TestParent>
),
});

await waitFor(() => {
expect(getByText("MOCK-EDIT-PAGE program-123")).toBeInTheDocument();
});
});

it("should render the ListView when no orgId param is provided", async () => {
const { getByText } = render(<OrganizationController />, {
wrapper: ({ children }) => <TestParent initialEntry="/programs">{children}</TestParent>,
});

await waitFor(() => {
expect(getByText("MOCK-LIST-PAGE")).toBeInTheDocument();
});
});
});
6 changes: 3 additions & 3 deletions src/content/organizations/Controller.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import { FC } from "react";
import { Navigate, useParams } from "react-router-dom";
import { Status, useAuthContext } from "../../components/Contexts/AuthContext";
import { OrganizationProvider } from "../../components/Contexts/OrganizationListContext";
Expand All @@ -18,12 +18,12 @@ const WrappedListView = () => (
*
* @returns The Organization Controller component
*/
const OrganizationController = () => {
const OrganizationController: FC = () => {
const { orgId } = useParams<{ orgId?: string }>();
const { user, status: authStatus } = useAuthContext();

if (authStatus === Status.LOADING) {
return <SuspenseLoader data-testid="studies-suspense-loader" />;
return <SuspenseLoader data-testid="organization-suspense-loader" />;
}

if (!hasPermission(user, "program", "manage")) {
Expand Down
18 changes: 12 additions & 6 deletions src/content/organizations/OrganizationView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import ConfirmDialog from "../../components/AdminPortal/Organizations/ConfirmDia
import usePageTitle from "../../hooks/usePageTitle";
import { filterAlphaNumeric, formatFullStudyName, mapOrganizationStudyToId } from "../../utils";
import { useSearchParamsContext } from "../../components/Contexts/SearchParamsContext";
import BaseAsterisk from "../../components/StyledFormComponents/StyledAsterisk";
import BaseSelect from "../../components/StyledFormComponents/StyledSelect";
import BaseOutlinedInput from "../../components/StyledFormComponents/StyledOutlinedInput";

Expand Down Expand Up @@ -142,7 +143,8 @@ const inactiveSubmissionStatus: SubmissionStatus[] = ["Completed"];
* @returns {JSX.Element}
*/
const OrganizationView: FC<Props> = ({ _id }: Props) => {
usePageTitle(`Organization ${!!_id && _id !== "new" ? _id : "Add"}`);
const isNew = _id && _id === "new";
usePageTitle(`${!isNew && _id ? "Edit" : "Add"} Program ${!isNew && _id ? _id : ""}`.trim());

const navigate = useNavigate();
const { enqueueSnackbar } = useSnackbar();
Expand Down Expand Up @@ -374,7 +376,6 @@ const OrganizationView: FC<Props> = ({ _id }: Props) => {
<StyledProfileIcon>
<img src={programIcon} alt="program icon" />
</StyledProfileIcon>

<StyledContentStack
direction="column"
justifyContent="center"
Expand All @@ -395,7 +396,9 @@ const OrganizationView: FC<Props> = ({ _id }: Props) => {
)}

<StyledField>
<StyledLabel id="organizationName">Program</StyledLabel>
<StyledLabel id="organizationName">
Program <BaseAsterisk />
</StyledLabel>
<StyledTextField
{...register("name", { required: true })}
inputProps={{ "aria-labelledby": "organizationName" }}
Expand All @@ -404,7 +407,9 @@ const OrganizationView: FC<Props> = ({ _id }: Props) => {
/>
</StyledField>
<StyledField>
<StyledLabel id="abbreviationLabel">Abbreviation</StyledLabel>
<StyledLabel id="abbreviationLabel">
Abbreviation <BaseAsterisk />
</StyledLabel>
<Controller
name="abbreviation"
control={control}
Expand Down Expand Up @@ -502,7 +507,9 @@ const OrganizationView: FC<Props> = ({ _id }: Props) => {
/>
</StyledField>
<StyledField>
<StyledLabel id="statusLabel">Status</StyledLabel>
<StyledLabel id="statusLabel">
Status <BaseAsterisk />
</StyledLabel>
<Controller
name="status"
control={control}
Expand All @@ -522,7 +529,6 @@ const OrganizationView: FC<Props> = ({ _id }: Props) => {
)}
/>
</StyledField>

<StyledButtonStack
direction="row"
justifyContent="center"
Expand Down
2 changes: 1 addition & 1 deletion src/content/questionnaire/ListView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ const ListingView: FC = () => {
defaultRowsPerPage={20}
defaultOrder="desc"
position="bottom"
noContentText="There are no submission requests associated with your account"
noContentText="You either do not have the appropriate permissions to view submission requests, or there are no submission requests associated with your account."
onFetchData={handleFetchData}
containerProps={{
sx: {
Expand Down
4 changes: 3 additions & 1 deletion src/content/questionnaire/sections/A.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ const StyledFormControlLabel = styled(FormControlLabel)({
"& .MuiFormControlLabel-label": {
color: "#083A50",
fontWeight: "700",
userSelect: "none",
},
"& .MuiCheckbox-root": {
"& .MuiCheckbox-root:not(.Mui-disabled)": {
color: "#005EA2 !important",
},
});
Expand Down Expand Up @@ -231,6 +232,7 @@ const FormSectionA: FC<FormSectionProps> = ({ SectionOption, refs }: FormSection
readOnly={readOnlyInputs}
/>
}
disabled={readOnlyInputs}
/>
<input
id="section-a-primary-contact-same-as-pi-checkbox"
Expand Down

0 comments on commit 8e06ec7

Please sign in to comment.