Skip to content

Commit

Permalink
feat(rbac frontend) unit tests (#84)
Browse files Browse the repository at this point in the history
* minor: renamed authentication folder and deleted unused signout button

* add roles to user session

* added icons

* adapt main menu

* refactor menu

* styling

* styling

* replaced jwt decode method

* replaced localization

* replaced localization

* use enum for roles

* main menu component test

* mnestix user as default role

* extract function for rendering

* bottom menu tests

* typo fix

* feat(rbac-frontend): added TextEncoder and Decoder

* feat(rbac-frontend): uppercase corrected

* fix variable name

---------

Co-authored-by: XITASO\pawel.baran <[email protected]>
  • Loading branch information
GailMelanie and pawel-baran-se authored Jan 31, 2025
1 parent e0ff0dc commit 80a411a
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 7 deletions.
7 changes: 6 additions & 1 deletion jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
import '@testing-library/jest-dom'
import '@testing-library/jest-dom';
import { TextDecoder, TextEncoder } from 'util';

global.TextEncoder = TextEncoder;
// @ts-ignore
global.TextDecoder = TextDecoder;
6 changes: 3 additions & 3 deletions src/app/env/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { EnvironmentalVariables, getEnv } from './env';
import { useAsyncEffect } from 'lib/hooks/UseAsyncEffect';
import { CenteredLoadingSpinner } from 'components/basics/CenteredLoadingSpinner';

const initialValues: EnvironmentalVariables = {
export const initialEnvValues: EnvironmentalVariables = {
AAS_LIST_FEATURE_FLAG: false,
COMPARISON_FEATURE_FLAG: false,
TRANSFER_FEATURE_FLAG: false,
Expand All @@ -28,14 +28,14 @@ const initialValues: EnvironmentalVariables = {
DATA_PRIVACY_URL: '',
};

export const EnvContext = createContext(initialValues);
export const EnvContext = createContext(initialEnvValues);

export const EnvProvider = ({
children,
}: Readonly<{
children: React.ReactNode;
}>) => {
const [env, setEnv] = useState<EnvironmentalVariables>(initialValues);
const [env, setEnv] = useState<EnvironmentalVariables>(initialEnvValues);
const [renderChildren, setChildren] = useState<boolean>(false);
useAsyncEffect(async () => {
const env = await getEnv();
Expand Down
40 changes: 40 additions & 0 deletions src/layout/menu/BottomMenu.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { CustomRender } from 'test-utils/CustomRender';
import { screen } from '@testing-library/react';
import { expect } from '@jest/globals';
import { useAuth } from 'lib/hooks/UseAuth';
import BottomMenu from 'layout/menu/BottomMenu';
import { MnestixRole } from 'components/authentication/AllowedRoutes';

jest.mock('../../lib/hooks/UseAuth');

const mockUseAuth = jest.fn(() => {
return {
getAccount: () => {},
isLoggedIn: false,
};
});

describe('BottomMenu', () => {
beforeAll(() => {
(useAuth as jest.Mock).mockImplementation(mockUseAuth);
});

it('should show the login button for not logged-in user', () => {
CustomRender(<BottomMenu isLoggedIn={false} name={''} mnestixRole={MnestixRole.MnestixGuest}></BottomMenu>);

const loginButton = screen.getByTestId('sidebar-button');
expect(loginButton).toHaveTextContent('Login');
});

it('should show the users name and logout button when logged in', () => {
CustomRender(
<BottomMenu isLoggedIn={true} name={'test user'} mnestixRole={MnestixRole.MnestixAdmin}></BottomMenu>,
);

const logoutButton = screen.getByTestId('sidebar-button');
expect(logoutButton).toHaveTextContent('Logout');

const name = screen.getByTestId('user-info-box');
expect(name).toHaveTextContent('test user');
});
});
2 changes: 1 addition & 1 deletion src/layout/menu/BottomMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default function BottomMenu(props: { isLoggedIn: boolean; name: string; m
{props.isLoggedIn && (
<>
<MenuHeading marginTop={0}>
<Box component="span" display="flex" gap={1}>
<Box component="span" display="flex" gap={1} data-testid="user-info-box">
{props.mnestixRole === MnestixRole.MnestixAdmin ? (
<AdminPanelSettings />
) : (
Expand Down
110 changes: 110 additions & 0 deletions src/layout/menu/MainMenu.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { CustomRender } from 'test-utils/CustomRender';
import MainMenu from 'layout/menu/MainMenu';
import { fireEvent, screen } from '@testing-library/react';
import { expect } from '@jest/globals';
import { useAuth } from 'lib/hooks/UseAuth';
import AllowedRoutes, { MnestixRole } from 'components/authentication/AllowedRoutes';
import { useEnv } from 'app/env/provider';

jest.mock('next-auth/react');
jest.mock('../../lib/hooks/UseAuth');
jest.mock('../../app/env/provider');

const mockEnvVariables = jest.fn(() => {
return {
AAS_LIST_FEATURE_FLAG: true,
MNESTIX_BACKEND_API_URL: 'http://localhost:5064/backend',
AUTHENTICATION_FEATURE_FLAG: true,
};
});

const mockUseAuthAdmin = jest.fn(() => {
return {
getAccount: () => {
return {
user: {
roles: [],
mnestixRole: MnestixRole.MnestixAdmin,
allowedRoutes: AllowedRoutes.mnestixAdmin,
},
};
},
isLoggedIn: true,
};
});

const mockUseAuthUser = jest.fn(() => {
return {
getAccount: () => {
return {
user: {
roles: [],
mnestixRole: MnestixRole.MnestixUser,
allowedRoutes: AllowedRoutes.mnestixUser,
},
};
},
isLoggedIn: true,
};
});

const mockUseAuthNotLoggedIn = jest.fn(() => {
return {
getAccount: () => {},
isLoggedIn: false,
};
});

function renderAndOpenMenu() {
CustomRender(<MainMenu></MainMenu>);
const burgerMenu = screen.getByTestId('header-burgermenu');
fireEvent.click(burgerMenu);
}

describe('MainMenu', () => {
beforeAll(() => {
(useEnv as jest.Mock).mockImplementation(mockEnvVariables);
});

it('should be able to open the menu', () => {
(useAuth as jest.Mock).mockImplementation(mockUseAuthAdmin);
renderAndOpenMenu();

const mainMenu = screen.getByTestId('main-menu');
expect(mainMenu).toBeInTheDocument();
});
describe('logged in as admin', () => {
it('should show all allowed admin actions', () => {
(useAuth as jest.Mock).mockImplementation(mockUseAuthAdmin);
renderAndOpenMenu();

const templates = screen.getByTestId('/templates');
expect(templates).toBeInTheDocument();

const settings = screen.getByTestId('/settings');
expect(settings).toBeInTheDocument();
});
});
describe('logged in user', () => {
it('should show all allowed user actions', () => {
(useAuth as jest.Mock).mockImplementation(mockUseAuthUser);
renderAndOpenMenu();

const templates = screen.getByTestId('/templates');
expect(templates).toBeInTheDocument();
});
});
describe('not logged in', () => {
it('should show all allowed not-logged-in actions', () => {
(useEnv as jest.Mock).mockImplementation(mockEnvVariables);
(useAuth as jest.Mock).mockImplementation(mockUseAuthNotLoggedIn);
renderAndOpenMenu();

const templates = screen.getByTestId('/');
expect(templates).toBeInTheDocument();

const list = screen.getByTestId('/list');
expect(list).toBeInTheDocument();
});
});
});
8 changes: 6 additions & 2 deletions src/layout/menu/MainMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,19 @@ export default function MainMenu() {
<MenuIcon />
</IconButton>
<StyledDrawer anchor="left" open={drawerOpen} onClose={handleMenuInteraction(false)}>
<Box onClick={handleMenuInteraction(false)} onKeyDown={handleMenuInteraction(false)}>
<Box
onClick={handleMenuInteraction(false)}
onKeyDown={handleMenuInteraction(false)}
data-testid="main-menu"
>
<List>
<MenuHeading>{t('repository')}</MenuHeading>
<>
{basicMenu.map((props, i) => (
<MenuListItem {...props} key={'adminMainMenu' + i} />
))}
</>
{useAuthentication && auth.isLoggedIn && (
{useAuthentication && !auth.isLoggedIn && (
<>
<StyledDivider />
<MenuHeading>{t('findOutMore')}</MenuHeading>
Expand Down
1 change: 1 addition & 0 deletions src/layout/menu/MenuListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function MenuListItem(props: MenuListItemProps) {

return props.to ? (
<ListItemButton
data-testid={props.to}
component={!props.external ? Link : 'a'}
href={props.to}
target={props.target}
Expand Down

0 comments on commit 80a411a

Please sign in to comment.