Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UserMenu] Unit tests: SiteSettings only visible to admins #641

Merged
merged 11 commits into from
Sep 16, 2020
95 changes: 55 additions & 40 deletions src/components/AppBar/UserMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,20 @@ import history from "../../history";
import theme from "../../types/theme";
import { User } from "../../types/user";

export async function getIsAdmin(): Promise<boolean> {
const userId = LocalStorage.getUserId();
return await getUser(userId)
.then((user: User) => {
return user.isAdmin;
})
.catch((err) => {
console.log(err);
return false;
});
}

/**
* Avatar in appbar with dropdown: site settings (for admins), user settings, log out
* Avatar in appbar with dropdown UserMenu
*/
export default function UserMenu() {
const [anchorElement, setAnchorElement] = React.useState<null | HTMLElement>(
Expand All @@ -27,21 +39,10 @@ export default function UserMenu() {
setAnchorElement(null);
}

async function getIsAdmin() {
const userId = LocalStorage.getUserId();
await getUser(userId)
.then((user: User) => {
setIsAdmin(user.isAdmin);
})
.catch((err) => console.log(err));
}

React.useEffect(() => {
getIsAdmin();
}, []);
getIsAdmin().then((result) => setIsAdmin(result));

return (
<div>
<React.Fragment>
<Button
aria-controls="user-menu"
aria-haspopup="true"
Expand All @@ -57,7 +58,6 @@ export default function UserMenu() {
getContentAnchorEl={null}
id="user-menu"
anchorEl={anchorElement}
keepMounted
open={Boolean(anchorElement)}
onClose={handleClose}
anchorOrigin={{
Expand All @@ -69,37 +69,52 @@ export default function UserMenu() {
horizontal: "right",
}}
>
{/* Only show Site Settings link to Admin users. */}
{isAdmin && (
<MenuItem
onClick={() => {
LocalStorage.setProjectId("");
history.push("/site-settings");
}}
>
<SettingsApplications style={{ marginRight: theme.spacing(1) }} />
<Translate id="userMenu.siteSettings" />
</MenuItem>
)}
<UserMenuList isAdmin={isAdmin} />
</Menu>
</React.Fragment>
);
}

<MenuItem
onClick={() => {
history.push("/user-settings");
}}
>
<Person style={{ marginRight: theme.spacing(1) }} />
<Translate id="userMenu.userSettings" />
</MenuItem>
interface UserMenuListProps {
isAdmin: boolean;
}

/**
* UserMenu options: site settings (for admins), user settings, log out
*/
export function UserMenuList(props: UserMenuListProps) {
return (
<React.Fragment>
{/* Only show Site Settings link to Admin users. */}
{props.isAdmin && (
<MenuItem
onClick={() => {
history.push("/login");
LocalStorage.setProjectId("");
history.push("/site-settings");
}}
>
<ExitToApp style={{ marginRight: theme.spacing(1) }} />
<Translate id="userMenu.logout" />
<SettingsApplications style={{ marginRight: theme.spacing(1) }} />
<Translate id="userMenu.siteSettings" />
</MenuItem>
</Menu>
</div>
)}

<MenuItem
onClick={() => {
history.push("/user-settings");
}}
>
<Person style={{ marginRight: theme.spacing(1) }} />
<Translate id="userMenu.userSettings" />
</MenuItem>

<MenuItem
onClick={() => {
history.push("/login");
}}
>
<ExitToApp style={{ marginRight: theme.spacing(1) }} />
<Translate id="userMenu.logout" />
</MenuItem>
</React.Fragment>
);
}
66 changes: 50 additions & 16 deletions src/components/AppBar/tests/UserMenu.test.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,54 @@
import { MenuItem, Button } from "@material-ui/core";
import React from "react";
import ReactDOM from "react-dom";
import configureMockStore from "redux-mock-store";
import { defaultState } from "../../App/DefaultState";
import { Provider } from "react-redux";
import UserMenu from "../UserMenu";
import renderer, { ReactTestRenderer } from "react-test-renderer";

const createMockStore = configureMockStore([]);
import { User } from "../../../types/user";
import UserMenu, { getIsAdmin, UserMenuList } from "../UserMenu";

it("renders without crashing", () => {
const mockStore = createMockStore(defaultState);
const div = document.createElement("div");
ReactDOM.render(
<Provider store={mockStore}>
<UserMenu />
</Provider>,
div
);
ReactDOM.unmountComponentAtNode(div);
const mockUser = new User("", "", "");
let testRenderer: ReactTestRenderer;

jest.mock("../../../backend", () => {
return {
getUser: jest.fn(() => {
return Promise.resolve(mockUser);
}),
};
});

beforeEach(() => {
jest.clearAllMocks();
});

describe("Tests UserMenu", () => {
it("renders without crashing", () => {
renderer.act(() => {
testRenderer = renderer.create(<UserMenu />);
});
expect(testRenderer.root.findAllByType(Button).length).toEqual(1);
});

it("should return correct value for isAdmin", (done) => {
mockUser.isAdmin = false;
getIsAdmin().then((result) => {
expect(result).toEqual(false);
mockUser.isAdmin = true;
getIsAdmin().then((result) => {
expect(result).toEqual(true);
done();
});
});
});

it("should only show site settings to general users", async () => {
renderer.act(() => {
testRenderer = renderer.create(<UserMenuList isAdmin={false} />);
});
const normalMenuItems = testRenderer.root.findAllByType(MenuItem).length;
renderer.act(() => {
testRenderer = renderer.create(<UserMenuList isAdmin={true} />);
});
const adminMenuItems = testRenderer.root.findAllByType(MenuItem).length;
expect(adminMenuItems).toBe(normalMenuItems + 1);
});
});