Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions frontend/__tests__/e2e/pages/Home.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { mockHomeData } from '@e2e/data/mockHomeData'
import { test, expect } from '@playwright/test'


test.describe('Home Page', () => {
test.beforeEach(async ({ page }) => {
await page.route('**/graphql/', async (route) => {
Expand Down Expand Up @@ -48,11 +49,11 @@ test.describe('Home Page', () => {
})

test('should have top contributors', async ({ page }) => {
await expect(page.getByRole('heading', { name: 'Top Contributors' })).toBeVisible()
await expect(page.getByRole('img', { name: 'Contributor 1' })).toBeVisible()
await expect(page.getByRole('link', { name: 'Project 21' })).toBeVisible()
await page.getByText('Contributor 1').click()
expect(page.url()).toContain('community/users/contributor1')
await expect(page.getByRole('heading', { name: 'Top Contributors' })).toBeVisible();
const contributors = page.getByTestId('top-contributor');
await expect(contributors.getByRole('img', {name: 'Contributor 1'})).toBeVisible();
await expect(contributors.getByText('Contributor 1')).toBeVisible();
await expect(page.getByText('Project 21')).toBeVisible();
})

test('should have recent issues', async ({ page }) => {
Expand Down
12 changes: 6 additions & 6 deletions frontend/__tests__/e2e/pages/ProjectDetails.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ test.describe('Project Details Page', () => {

test('should have top contributors', async ({ page }) => {
await expect(page.getByRole('heading', { name: 'Top Contributors' })).toBeVisible()
await expect(page.getByRole('img', { name: 'Contributor 1' })).toBeVisible()
await expect(page.getByText('Contributor 1')).toBeVisible()
await expect(page.getByText('30 Contributions')).toBeVisible()
await expect(page.getByRole('img', { name: 'Contributor 2' })).toBeVisible()
await expect(page.getByText('Contributor 2')).toBeVisible()
await expect(page.getByText('29 Contributions')).toBeVisible()
await expect(page.getByRole('img', {name: 'Contributor 1'})).toBeVisible();
await expect(page.getByText('Contributor 1')).toBeVisible();
await expect(page.getByText('30 Contributions')).toBeVisible();
await expect(page.getByRole('img', {name: 'Contributor 1'})).toBeVisible();
await expect(page.getByText('Contributor 2')).toBeVisible();
await expect(page.getByText('29 Contributions')).toBeVisible();
})

test('toggle top contributors', async ({ page }) => {
Expand Down
4 changes: 2 additions & 2 deletions frontend/__tests__/unit/pages/ChapterDetails.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ describe('chapterDetailsPage Component', () => {
...mockChapterDetailsData,
topContributors: [
{
name: 'user1',
name: 'Contributor 1',
avatarUrl: 'https://example.com/avatar1.jpg',
contributionsCount: 30,
},
Expand All @@ -100,7 +100,7 @@ describe('chapterDetailsPage Component', () => {
render(<ChapterDetailsPage />)

await waitFor(() => {
expect(screen.getByText('user1')).toBeInTheDocument()
expect(screen.getByText('Contributor 1')).toBeInTheDocument()
})
})
})
4 changes: 2 additions & 2 deletions frontend/__tests__/unit/pages/CommitteeDetails.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('CommitteeDetailsPage Component', () => {
{
avatarUrl: 'https://example.com/avatar1.jpg',
contributionsCount: 30,
login: 'user1',
login: 'Contributor 1',
name: '',
__typename: 'UserNode',
},
Expand All @@ -94,7 +94,7 @@ describe('CommitteeDetailsPage Component', () => {
render(<CommitteeDetailsPage />)

await waitFor(() => {
expect(screen.getByText('user1')).toBeInTheDocument()
expect(screen.getByText('Contributor 1')).toBeInTheDocument()
})
})

Expand Down
12 changes: 11 additions & 1 deletion frontend/src/components/CardDetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,17 @@ const DetailsCard = ({
{topics.length !== 0 && <ToggleableList items={topics} label="Topics" />}
</div>
)}
<TopContributors contributors={topContributors} maxInitialDisplay={6} />
<TopContributors
contributors={topContributors}
renderDetails={(item) => (
<div className="mt-2 flex flex-shrink-0 items-center text-sm text-gray-600 dark:text-gray-300">
<span className="overflow-hidden text-ellipsis whitespace-nowrap">
{item.contributionsCount} contributions
</span>
</div>
)}
maxInitialDisplay={6}
/>
{(type === 'project' || type === 'repository') && (
<div className="grid-cols-2 gap-4 lg:grid">
<ItemCardList
Expand Down
55 changes: 19 additions & 36 deletions frontend/src/components/ToggleContributors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ import { Button } from '@chakra-ui/react'
import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useState } from 'react'
import { JSX } from 'react'
import { useNavigate } from 'react-router-dom'
import { TopContributorsTypeGraphql } from 'types/contributor'
import { capitalize } from 'utils/capitalize'
const TopContributors = ({
contributors,
label = 'Top Contributors',
maxInitialDisplay = 6,
className = '',
renderDetails,
}: {
contributors: TopContributorsTypeGraphql[]
label?: string
maxInitialDisplay?: number
className?: string
renderDetails: (item: { contributionsCount: number; projectName?: string }) => JSX.Element
}) => {
const navigate = useNavigate()
const [showAllContributors, setShowAllContributors] = useState(false)
Expand All @@ -23,51 +27,30 @@ const TopContributors = ({
const displayContributors = showAllContributors
? contributors
: contributors.slice(0, maxInitialDisplay)

if (contributors.length === 0) {
return
}
return (
<div className={`mb-8 rounded-lg bg-gray-100 p-6 shadow-md dark:bg-gray-800 ${className}`}>
<h2 className="mb-4 text-2xl font-semibold">{label}</h2>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3">
{displayContributors.map((contributor, index) => (
<div
<div className="grid gap-x-5 sm:grid-cols-2 md:grid-cols-3">
{displayContributors.map((item, index) => (
<button
key={index}
className="flex cursor-pointer items-center space-x-3 rounded-lg p-3 hover:bg-gray-200 dark:hover:bg-gray-700"
data-testid="top-contributor"
onClick={() => navigate(`/community/users/${item.login}`)}
className="mb-4 w-full rounded-lg bg-gray-200 p-4 dark:bg-gray-700"
>
<img
src={`${contributor?.avatarUrl}&s=60`}
alt={contributor.name || contributor.login}
className="mr-3 h-10 w-10 rounded-full"
/>
<div>
<button
onClick={() => navigate(`/community/users/${contributor.login}`)}
className="m-0 border-none bg-transparent p-0 font-semibold text-blue-600 hover:underline dark:text-sky-400"
style={{ all: 'unset', cursor: 'pointer' }}
>
{contributor.name || contributor.login}
</button>

{contributor?.projectName ? (
<p className="text-sm text-gray-600 dark:text-gray-400">
<a
href={contributor.projectUrl}
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:underline dark:text-sky-400"
>
{contributor.projectName}
</a>
</p>
) : (
<p className="text-sm text-gray-600 dark:text-gray-400">
{contributor?.contributionsCount} contributions
</p>
)}
<div className="flex w-full flex-col justify-between">
<div className="flex w-full items-center gap-2">
<img src={item?.avatarUrl} alt={item?.name} className="h-6 w-6 rounded-full" />
<h3 className="overflow-hidden text-ellipsis whitespace-nowrap font-semibold text-blue-500">
{capitalize(item.name) || capitalize(item.login)}
</h3>
</div>
<div className="ml-0.5 w-full">{renderDetails(item)}</div>
</div>
</div>
</button>
))}
</div>
{contributors.length > maxInitialDisplay && (
Expand Down
Loading