Skip to content

Commit

Permalink
feat: team list refactor and tests (#1168)
Browse files Browse the repository at this point in the history
Co-authored-by: Guido <stereopt@gmail.com>
  • Loading branch information
jpvsalvador and StereoPT authored Mar 1, 2023
1 parent 76551c0 commit ad585bc
Show file tree
Hide file tree
Showing 19 changed files with 169 additions and 150 deletions.
29 changes: 14 additions & 15 deletions frontend/src/components/Teams/TeamsList/TeamItem/TeamItem.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { TeamUserRoles } from '@/utils/enums/team.user.roles';
import TeamItem, { TeamItemProps } from './index';

const DEFAULT_PROPS = {
userId: '',
team: TeamFactory.create(),
};

Expand All @@ -18,8 +17,13 @@ jest.mock('next/router', () => ({
useRouter: () => router,
}));

const render = (props: TeamItemProps = DEFAULT_PROPS) =>
renderWithProviders(<TeamItem {...props} />, { routerOptions: router });
const render = (props: TeamItemProps = DEFAULT_PROPS, options?: any) =>
renderWithProviders(<TeamItem {...props} />, {
routerOptions: router,
sessionOptions: {
user: options?.user,
},
});

describe('Components/TeamItem', () => {
let testProps: TeamItemProps;
Expand All @@ -32,10 +36,9 @@ describe('Components/TeamItem', () => {
const teamItemProps = { ...testProps };

// Act
const { getByTestId, getByText } = render(teamItemProps);
const { getByText } = render(teamItemProps);

// Assert
expect(getByTestId('teamitemTitle')).toBeInTheDocument();
expect(getByText(teamItemProps.team.name)).toBeInTheDocument();
});

Expand All @@ -50,11 +53,10 @@ describe('Components/TeamItem', () => {
};

// Act
const { getByTestId } = render(teamItemProps);
const { getByText } = render(teamItemProps);

// Assert
expect(getByTestId('teamitemBoards')).toBeInTheDocument();
expect(getByTestId('teamitemBoards')).toHaveTextContent('3 team boards');
expect(getByText('3 team boards')).toBeInTheDocument();
});

it('should render no team boards', () => {
Expand All @@ -68,18 +70,16 @@ describe('Components/TeamItem', () => {
};

// Act
const { getByTestId } = render(teamItemProps);
const { getByText } = render(teamItemProps);

// Assert
expect(getByTestId('teamitemBoards')).toBeInTheDocument();
expect(getByTestId('teamitemBoards')).toHaveTextContent('No boards');
expect(getByText('No boards')).toBeInTheDocument();
});

it('should render create first board', () => {
// Arrange
const teamAdmin = TeamUserFactory.create({ role: TeamUserRoles.ADMIN });
const teamItemProps = {
userId: teamAdmin.user._id,
team: {
...testProps.team,
boardsCount: 0,
Expand All @@ -88,10 +88,9 @@ describe('Components/TeamItem', () => {
};

// Act
const { getByTestId } = render(teamItemProps);
const { getByText } = render(teamItemProps, { user: teamAdmin.user });

// Assert
expect(getByTestId('teamitemBoards')).toBeInTheDocument();
expect(getByTestId('teamitemBoards')).toHaveTextContent('Create first board');
expect(getByText('Create first board')).toBeInTheDocument();
});
});
9 changes: 3 additions & 6 deletions frontend/src/components/Teams/TeamsList/TeamItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,15 @@ const InnerContainer = styled(Flex, Box, {
});

export type TeamItemProps = {
userId: string | undefined;
team: Team;
isTeamPage?: boolean;
};

const TeamItem = React.memo<TeamItemProps>(({ userId, team, isTeamPage }) => {
const TeamItem = React.memo<TeamItemProps>(({ team, isTeamPage }) => {
const { data: session } = useSession();

const router = useRouter();

const isSAdmin = session?.user.isSAdmin;

const { id: userId, isSAdmin } = { ...session?.user };
const { id, users, name } = team;
const userFound: TeamUser | undefined = users.find((member) => member.user?._id === userId);
const userRole = userFound?.role;
Expand All @@ -61,7 +58,7 @@ const TeamItem = React.memo<TeamItemProps>(({ userId, team, isTeamPage }) => {
}, [isSAdmin, team, userId]);

return (
<Flex direction="column">
<Flex direction="column" data-testid="teamItem">
<InnerContainer align="center" elevation="1" gap="40">
<Flex align="center" gap="8" css={{ flex: '1' }}>
<Icon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type TeamTitleProps = {

const TeamTitle = ({ teamId, title, isTeamPage }: TeamTitleProps) => {
const renderTitle = () => (
<Text link={isTeamPage} size="sm" fontWeight="bold" overflow="wrap" data-testid="teamitemTitle">
<Text link={isTeamPage} size="sm" fontWeight="bold" overflow="wrap">
{title}
</Text>
);
Expand Down
52 changes: 52 additions & 0 deletions frontend/src/components/Teams/TeamsList/TeamsList.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { createMockRouter } from '@/utils/testing/mocks';
import { renderWithProviders } from '@/utils/testing/renderWithProviders';
import { TeamFactory } from '@/utils/factories/team';
import { fireEvent, waitFor } from '@testing-library/react';
import { ROUTES } from '@/utils/routes';
import TeamsList, { TeamsListProps } from '.';

const DEFAULT_PROPS = {
teams: TeamFactory.createMany(3),
};

const router = createMockRouter({ pathname: '/teams' });

jest.mock('next/router', () => ({
useRouter: () => router,
}));

const render = (props: TeamsListProps = DEFAULT_PROPS) =>
renderWithProviders(<TeamsList {...props} />, { routerOptions: router });

describe('Components/TeamsList', () => {
let testProps: TeamsListProps;
beforeEach(() => {
testProps = { ...DEFAULT_PROPS };
});

it('should render correctly', () => {
// Arrange
const teamItemProps = { ...testProps };

// Act
const { getAllByTestId } = render(teamItemProps);

// Assert
expect(getAllByTestId('teamItem')).toHaveLength(teamItemProps.teams.length);
});

it('should render empty state correctly', async () => {
// Arrange
const teamItemProps = { ...testProps, teams: [] };

// Act
const { getByTestId, getByText } = render(teamItemProps);
fireEvent.click(getByText('Create your first team'));

// Assert
expect(getByTestId('emptyTeams')).toBeInTheDocument();
await waitFor(() => {
expect(router.push).toHaveBeenCalledWith(ROUTES.NewTeam, ROUTES.NewTeam, expect.anything());
});
});
});
18 changes: 12 additions & 6 deletions frontend/src/components/Teams/TeamsList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import React from 'react';

import { Team } from '@/types/team/team';
import Flex from '@/components/Primitives/Flex';
import EmptyTeams from './partials/EmptyTeams';
import ListOfCards from './partials/ListOfCards';

type TeamsListProps = {
userId: string;
import TeamItem from './TeamItem';

export type TeamsListProps = {
teams: Team[];
isFetching: boolean;
};

const TeamsList = ({ userId, teams, isFetching }: TeamsListProps) => {
const TeamsList = ({ teams }: TeamsListProps) => {
if (teams?.length === 0) return <EmptyTeams />;

return <ListOfCards isLoading={isFetching} teams={teams} userId={userId} />;
return (
<Flex direction="column" gap="8">
{teams.map((team: Team) => (
<TeamItem key={team.id} team={team} isTeamPage />
))}
</Flex>
);
};

export default TeamsList;
37 changes: 37 additions & 0 deletions frontend/src/components/Teams/TeamsList/partials/EmptyTeams.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { styled } from '@/styles/stitches/stitches.config';
import Link from 'next/link';

import Text from '@/components/Primitives/Text';
import Box from '@/components/Primitives/Box';
import Flex from '@/components/Primitives/Flex';

import EmptyTeamsImage from '@/components/images/EmptyTeams';

const StyledBox = styled(Flex, Box, {
position: 'relative',
borderRadius: '$12',
backgroundColor: 'white',
mt: '$14',
p: '$48',
});

const EmptyTeams = () => (
<StyledBox
align="center"
direction="column"
elevation="1"
justify="center"
data-testid="emptyTeams"
>
<EmptyTeamsImage />
<Text css={{ mt: '$40', textAlign: 'center' }} size="md">
<Link href="/teams/new">
<Text link fontWeight="medium">
Create your first team
</Text>
</Link>{' '}
now.
</Text>
</StyledBox>
);
export default EmptyTeams;

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

5 changes: 1 addition & 4 deletions frontend/src/components/Users/UserEdit/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@ import React from 'react';
import ListOfCards from './partials/ListOfCards';

type UserEditProps = {
userId: string | undefined;
isLoading: boolean;
};

const UsersEdit = ({ userId, isLoading }: UserEditProps) => (
<ListOfCards userId={userId} isLoading={isLoading} />
);
const UsersEdit = ({ isLoading }: UserEditProps) => <ListOfCards isLoading={isLoading} />;

export default UsersEdit;
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,17 @@ import { useRecoilValue } from 'recoil';
import { userTeamsListState } from '@/store/team/atom/team.atom';

type ListOfCardsProp = {
userId: string | undefined;
isLoading: boolean;
};

const ListOfCards = React.memo<ListOfCardsProp>(({ userId, isLoading }) => {
const ListOfCards = React.memo<ListOfCardsProp>(({ isLoading }) => {
const teamsOfUsers = useRecoilValue(userTeamsListState);

return (
<ScrollableContent direction="column" gap="24" justify="start">
<Flex direction="column" gap="8">
{teamsOfUsers?.map((team: Team) => (
<TeamItem key={team.id} team={team} userId={userId} isTeamPage={false} />
<TeamItem key={team.id} team={team} isTeamPage={false} />
))}
</Flex>
{isLoading && (
Expand Down
Loading

0 comments on commit ad585bc

Please sign in to comment.