diff --git a/__tests__/page/team-details/about.test.tsx b/__tests__/page/team-details/about.test.tsx new file mode 100644 index 00000000..c2d1f17e --- /dev/null +++ b/__tests__/page/team-details/about.test.tsx @@ -0,0 +1,134 @@ +import { render, screen, fireEvent } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import About from '@/components/page/team-details/about'; +import { IUserInfo } from '@/types/shared.types'; +import { ITeam, ITag } from '@/types/teams.types'; +import Cookies from 'js-cookie'; +import { updateTeam } from '@/services/teams.service'; + +const mockAnalytics = { + onTeamDetailAboutShowMoreClicked: jest.fn(), + onTeamDetailAboutShowLessClicked: jest.fn(), + onTeamDetailAboutEditClicked: jest.fn(), + onTeamDetailAboutEditCancelClicked: jest.fn(), + onTeamDetailAboutEditSaveClicked: jest.fn(), + recordAboutSave: jest.fn(), +}; + +jest.mock('@/analytics/teams.analytics', () => ({ + useTeamAnalytics: () => mockAnalytics, +})); + +// jest.mock('js-cookie', () => ({ +// get: jest.fn().mockReturnValue('"mockAuthToken"'), +// })); + +jest.mock('@/services/teams.service', () => ({ + updateTeam: jest.fn().mockResolvedValue({ data: {}, isError: false }), +})); + +jest.mock('react-toastify', () => ({ + toast: { + error: jest.fn(), + success: jest.fn(), + }, +})); + +beforeEach(() => { + jest.clearAllMocks(); + }); + +describe('About Component', () => { + const team: ITeam = { + id: '1', + name: 'Team A', + contactMethod: 'Email', + technologies: [{ title: 'React' }, { title: 'Node.js' }], + industryTags: [{ title: 'Tech' }], + fundingStage: { title: 'Seed' }, + membershipSources: [{ title: 'Source A' }], + logoUid: 'logo123', + maintainingProjects: [], + contributingProjects: [], + teamFocusAreas: [] + }; + + const userInfo: IUserInfo = { + name: 'User A', + }; + + const props = { + about: 'This is a test about content.', + team, + userInfo, + hasTeamEditAccess: true, + }; + + it('renders About component', () => { + render(); + expect(screen.getByText('About')).toBeInTheDocument(); + expect(screen.getByText('This is a test about content.')).toBeInTheDocument(); + }); + + it('shows more content when "show more" is clicked', () => { + props.about = 'This is a test about content. '.repeat(20); + render(); + fireEvent.click(screen.getByText('show more')); + expect(mockAnalytics.onTeamDetailAboutShowMoreClicked).toHaveBeenCalled(); + }); + + it('shows less content when "show less" is clicked', () => { + render(); + fireEvent.click(screen.getByText('show more')); + fireEvent.click(screen.getByText('show less')); + expect(mockAnalytics.onTeamDetailAboutShowLessClicked).toHaveBeenCalled(); + }); + + it('enables editor when "Edit" is clicked', () => { + const { container } = render(); + fireEvent.click(screen.getByText('Edit')); + expect(mockAnalytics.onTeamDetailAboutEditClicked).toHaveBeenCalled(); + expect(container.querySelector('.about__header__action__cancel__txt')?.textContent).toBe('Cancel'); // + expect(screen.getByText('Save')).toBeInTheDocument(); + }); + + it('cancels editing when "Cancel" is clicked', async () => { + props.about = 'This is a test about content.'; + const { container } = render(); + fireEvent.click(screen.getByText('Edit')); + const cancel = container.querySelector('.about__header__action__cancel__txt'); + if(cancel){ + expect(cancel?.textContent).toBe('Cancel'); // + await fireEvent.click(cancel); + expect(mockAnalytics.onTeamDetailAboutEditCancelClicked).toHaveBeenCalled(); + } + expect(screen.getByText('This is a test about content.')).toBeInTheDocument(); + }); + + it('saves edited content when "Save" is clicked', async () => { + Cookies.get = jest.fn().mockReturnValue('"mockAuthToken"'); + render(); + await fireEvent.click(screen.getByText('Edit')); + fireEvent.click(screen.getByText('Save')); + expect(mockAnalytics.onTeamDetailAboutEditSaveClicked).toHaveBeenCalled(); + expect(updateTeam).toHaveBeenCalled(); + }); + + it('save fails when "Save" is clicked', async () => { + Cookies.get = jest.fn().mockReturnValue(undefined); + render(); + await fireEvent.click(screen.getByText('Edit')); + await fireEvent.click(screen.getByText('Save')); + expect(updateTeam).not.toHaveBeenCalled(); + }); + + it('updateTeam fails "Save" is clicked', async () => { + Cookies.get = jest.fn().mockReturnValue('"mockAuthToken"'); + (updateTeam as jest.Mock).mockResolvedValue({ data: {}, isError: true }); + render(); + await fireEvent.click(screen.getByText('Edit')); + await fireEvent.click(screen.getByText('Save')); + expect(mockAnalytics.recordAboutSave).toHaveBeenCalled(); + }); + +}); \ No newline at end of file diff --git a/components/page/team-details/about.tsx b/components/page/team-details/about.tsx index fe33c3a5..d7a074a4 100644 --- a/components/page/team-details/about.tsx +++ b/components/page/team-details/about.tsx @@ -15,6 +15,19 @@ interface IAbout { userInfo: IUserInfo | undefined; hasTeamEditAccess: boolean; } +/** + * The `About` component displays and manages the "About" section of a team. + * It allows users to view, edit, and save the team's description. + * + * @param {IAbout} props - The properties passed to the component. + * @param {string} props.about - The initial content of the "About" section. + * @param {boolean} props.hasTeamEditAccess - Flag indicating if the user has edit access. + * @param {object} props.userInfo - Information about the current user. + * @param {object} props.team - Information about the team. + * + * @returns {JSX.Element} The rendered "About" component. + * + */ const About = (props: IAbout) => { const contentLength = 347; const [aboutContent, setAboutContent] = useState(props?.about);