Skip to content

Commit

Permalink
test & refactor: fix tests warnings (#2318)
Browse files Browse the repository at this point in the history
* test: mock use-places-autocomplite hook

* refactor: change overlay to menu on Dropdowns

* refactor: wrap location.href set into a function, update tests

* refactor: extract renderItem function

* refactor: migrate MentorStatsModal to React Functional Component

* refactor: migrate CoreJsIviewModal to React Functional Component

* test: fix async/await issues in tests
  • Loading branch information
I-vasilich-I authored Oct 16, 2023
1 parent 8194714 commit d7be41b
Show file tree
Hide file tree
Showing 18 changed files with 300 additions and 243 deletions.
69 changes: 41 additions & 28 deletions client/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import Link from 'next/link';
import { useRouter } from 'next/router';
import { Fragment, useContext, useMemo } from 'react';
import { useContext, useMemo } from 'react';
import { Button, Dropdown, Menu, Space } from 'antd';
import type { MenuProps } from 'antd';
import {
EyeOutlined,
LogoutOutlined,
Expand All @@ -14,17 +15,20 @@ import { SolidarityUkraine } from './SolidarityUkraine';
import { SessionContext } from 'modules/Course/contexts';
import { getNavigationItems } from 'modules/Home/data/links';
import { useActiveCourseContext } from 'modules/Course/contexts/ActiveCourseContext';
import css from 'styled-jsx/css';

type Props = {
showCourseName?: boolean;
title?: string;
};

type MenuItem = Required<MenuProps>['items'][number];

const MENU_ITEMS = [
{
link: '/profile',
icon: <EyeOutlined />,
title: 'View',
title: 'Profile',
},
{
link: '/profile/notifications',
Expand All @@ -51,26 +55,29 @@ const MENU_ITEMS = [

export function Header({ title, showCourseName }: Props) {
const { asPath: currentRoute } = useRouter();
const menuActiveItemStyle = { backgroundColor: '#e0f2ff' };

const session = useContext(SessionContext);
const { course } = useActiveCourseContext();
const courseLinks = useMemo(() => getNavigationItems(session, course ?? null), [course]);

const menu = (
<Menu>
{MENU_ITEMS.map(({ link, icon, title, target }, id, arr) => (
<Fragment key={id}>
{id === arr.length - 1 ? <Menu.Divider /> : null}
<Menu.Item key={id} style={currentRoute === link ? menuActiveItemStyle : undefined}>
<Button type="link" target={target} href={link} style={{ textAlign: 'left', width: '100%' }}>
{icon} {title}
</Button>
</Menu.Item>
</Fragment>
))}
</Menu>
);
const menuItems = useMemo((): MenuProps['items'] => {
const items = MENU_ITEMS.map(({ title, link, target, icon }) => {
const isActive = currentRoute === link;

return {
key: title,
label: (
<Button type="link" target={target} href={link} className={isActive ? 'menu-item-active' : undefined}>
{icon} {title}
</Button>
),
};
});

const lastItem = items.pop() as MenuItem;

return [...items, { type: 'divider' }, lastItem];
}, [currentRoute]);

return (
<Space
Expand Down Expand Up @@ -104,25 +111,31 @@ export function Header({ title, showCourseName }: Props) {
</div>
<div className="profile">
{session.githubId && (
<Dropdown overlay={menu} trigger={['click']}>
<Dropdown menu={{ items: menuItems }} trigger={['click']}>
<Button type="link">
<GithubAvatar githubId={session?.githubId} size={32} />
</Button>
</Dropdown>
)}
</div>
<style jsx>{`
@media all and (max-width: 768px) {
.title {
width: 100%;
order: 3;
text-align: center;
margin-top: 16px;
}
}
`}</style>
<style jsx>{styles}</style>
</nav>
<Menu selectedKeys={[currentRoute]} mode="horizontal" items={courseLinks} />
</Space>
);
}

const styles = css`
:global(li:has(.menu-item-active)) {
background-color: #e0f2ff;
}
@media all and (max-width: 768px) {
.title {
width: 100%;
order: 3;
text-align: center;
margin-top: 16px;
}
}
`;
93 changes: 45 additions & 48 deletions client/src/components/Profile/CoreJsIviewsModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { CoreJsInterviewsData } from './CoreJsIviewsCard';
import { Modal, Table, Typography, Tag } from 'antd';
import { memo } from 'react';
import { CoreJsInterviewsData } from './CoreJsIviewsCard';

const { Text } = Typography;

Expand All @@ -11,53 +11,50 @@ type Props = {
onHide: () => void;
};

class CoreJsIviewsModal extends React.PureComponent<Props> {
render() {
const { stats, isVisible, onHide, interviewIndex } = this.props;
const { courseFullName, interviews } = stats;
const { score, comment, answers, interviewer } = interviews[interviewIndex];
const CoreJsIviewsModal = ({ stats, isVisible, onHide, interviewIndex }: Props) => {
const { courseFullName, interviews } = stats;
const { score, comment, answers, interviewer } = interviews[interviewIndex];

return (
<Modal
title={`${courseFullName} CoreJS Interview Feedback`}
open={isVisible}
onCancel={onHide}
footer={null}
width={'80%'}
>
<p style={{ marginBottom: 5 }}>
Score: <Text mark>{score}</Text>
</p>
return (
<Modal
title={`${courseFullName} CoreJS Interview Feedback`}
open={isVisible}
onCancel={onHide}
footer={null}
width={'80%'}
>
<p style={{ marginBottom: 5 }}>
Score: <Text mark>{score}</Text>
</p>
<p style={{ marginBottom: 20 }}>
Interviewer: <a href={`/profile?githubId=${interviewer.githubId}`}>{interviewer.name}</a>
</p>
{comment && (
<p style={{ marginBottom: 20 }}>
Interviewer: <a href={`/profile?githubId=${interviewer.githubId}`}>{interviewer.name}</a>
<Text strong>Comment: </Text>
{comment}
</p>
{comment && (
<p style={{ marginBottom: 20 }}>
<Text strong>Comment: </Text>
{comment}
</p>
)}
<Table
data-testid="profile-corejs-iviews-modal-table"
dataSource={answers}
size="small"
rowKey="questionId"
pagination={false}
columns={[
{
dataIndex: 'questionText',
ellipsis: true,
},
{
dataIndex: 'answer',
render: answer =>
answer === true ? <Tag color="green">Yes</Tag> : answer === false ? <Tag color="red">No</Tag> : answer,
},
]}
/>
</Modal>
);
}
}
)}
<Table
data-testid="profile-corejs-iviews-modal-table"
dataSource={answers}
size="small"
rowKey="questionId"
pagination={false}
columns={[
{
dataIndex: 'questionText',
ellipsis: true,
},
{
dataIndex: 'answer',
render: answer =>
answer === true ? <Tag color="green">Yes</Tag> : answer === false ? <Tag color="red">No</Tag> : answer,
},
]}
/>
</Modal>
);
};

export default CoreJsIviewsModal;
export default memo(CoreJsIviewsModal);
105 changes: 51 additions & 54 deletions client/src/components/Profile/MentorStatsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,61 +13,58 @@ type Props = {
onHide: () => void;
};

class MentorStatsModal extends React.Component<Props> {
render() {
const { stats, isVisible, onHide } = this.props;
const { courseName, students } = stats;
const MentorStatsModal = ({ stats, isVisible, onHide }: Props) => {
const { courseName, students } = stats;

return (
<Modal title={`${courseName} statistics`} open={isVisible} onCancel={onHide} footer={null} width={'80%'}>
<Row gutter={[16, 16]}>
{students?.map(({ name, githubId, isExpelled, totalScore, repoUrl }) => {
const profile = `/profile?githubId=${githubId}`;
const guithubLink = `https://github.com/${githubId}`;
return (
<Modal title={`${courseName} statistics`} open={isVisible} onCancel={onHide} footer={null} width={'80%'}>
<Row gutter={[16, 16]}>
{students?.map(({ name, githubId, isExpelled, totalScore, repoUrl }) => {
const profile = `/profile?githubId=${githubId}`;
const guithubLink = `https://github.com/${githubId}`;

return (
<Col
key={`mentor-stats-modal-student-${githubId}`}
xs={{ span: 24 }}
sm={{ span: 12 }}
md={{ span: 8 }}
lg={{ span: 6 }}
>
<Row style={{ marginBottom: 24 }} justify="space-between">
<Col>
<div style={{ fontSize: 16, marginBottom: 16 }}>
<GithubAvatar githubId={githubId} size={48} style={{ marginRight: 24 }} />
<Text strong>
<a href={profile}>{name}</a>
</Text>
</div>
<p style={{ marginBottom: 5 }}>
{isExpelled ? <Tag color="red">expelled</Tag> : <Tag color="green">active</Tag>}
</p>
<p style={{ marginBottom: 5 }}>
Score: <Text mark>{totalScore}</Text>
</p>
<p style={{ marginBottom: 5 }}>
<GithubOutlined />{' '}
<a href={guithubLink} target="_blank">
{githubId}
</a>
</p>
<p style={{ marginBottom: 5 }}>
<LockFilled />{' '}
<a href={repoUrl} target="_blank">
{repoUrl?.split('/').pop()}
</a>
</p>
</Col>
</Row>
</Col>
);
})}
</Row>
</Modal>
);
}
}
return (
<Col
key={`mentor-stats-modal-student-${githubId}`}
xs={{ span: 24 }}
sm={{ span: 12 }}
md={{ span: 8 }}
lg={{ span: 6 }}
>
<Row style={{ marginBottom: 24 }} justify="space-between">
<Col>
<div style={{ fontSize: 16, marginBottom: 16 }}>
<GithubAvatar githubId={githubId} size={48} style={{ marginRight: 24 }} />
<Text strong>
<a href={profile}>{name}</a>
</Text>
</div>
<p style={{ marginBottom: 5 }}>
{isExpelled ? <Tag color="red">expelled</Tag> : <Tag color="green">active</Tag>}
</p>
<p style={{ marginBottom: 5 }}>
Score: <Text mark>{totalScore}</Text>
</p>
<p style={{ marginBottom: 5 }}>
<GithubOutlined />{' '}
<a href={guithubLink} target="_blank">
{githubId}
</a>
</p>
<p style={{ marginBottom: 5 }}>
<LockFilled />{' '}
<a href={repoUrl} target="_blank">
{repoUrl?.split('/').pop()}
</a>
</p>
</Col>
</Row>
</Col>
);
})}
</Row>
</Modal>
);
};

export default MentorStatsModal;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { act, render, screen } from '@testing-library/react';
import CoreJsIviewsCard, { CoreJsInterviewsData } from '../CoreJsIviewsCard';

describe('CoreJSIviewsCard', () => {
Expand Down Expand Up @@ -43,7 +43,11 @@ describe('CoreJSIviewsCard', () => {
render(<CoreJsIviewsCard data={data} />);

const btn = await screen.findByTestId('profile-corejs-iview-button');
btn.click();

act(() => {
btn.click();
});

const modal = await screen.findByTestId('profile-corejs-iviews-modal-table');
expect(modal).toBeInTheDocument();
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { render } from '@testing-library/react';
import { MentorStatsCard } from '../MentorStatsCard';
import * as reactUse from 'react-use';

describe('MentorStatsCard', () => {
const mentorStats = [
Expand Down Expand Up @@ -31,6 +32,8 @@ describe('MentorStatsCard', () => {
];

it('should render correctly', () => {
jest.spyOn(reactUse, 'useAsync').mockReturnValue({ value: null, loading: false });

const { container } = render(<MentorStatsCard githubId="test" data={mentorStats} />);
expect(container).toMatchSnapshot();
});
Expand Down
4 changes: 2 additions & 2 deletions client/src/modules/AutoTest/components/Coding/Coding.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ describe('Coding', () => {
${CourseTaskDetailedDtoTypeEnum.Kotlintask} | ${/https:\/\/github.com\/github-id\/github-repo-name/i}
`(
'should render $type task with $text',
({ type, text }: { type: CourseTaskDetailedDtoTypeEnum; text: RegExp | string }) => {
async ({ type, text }: { type: CourseTaskDetailedDtoTypeEnum; text: RegExp | string }) => {
renderCoding(type);

expect(screen.getByText(text)).toBeInTheDocument();
expect(await screen.findByText(text)).toBeInTheDocument();
},
);
});
Loading

0 comments on commit d7be41b

Please sign in to comment.