diff --git a/frontend/__tests__/unit/components/IssuesTable.test.tsx b/frontend/__tests__/unit/components/IssuesTable.test.tsx
index d6f7a05835..f9c805d183 100644
--- a/frontend/__tests__/unit/components/IssuesTable.test.tsx
+++ b/frontend/__tests__/unit/components/IssuesTable.test.tsx
@@ -2,6 +2,7 @@ import { render, screen, fireEvent, within } from '@testing-library/react'
import '@testing-library/jest-dom'
import React from 'react'
import IssuesTable, { type IssueRow } from 'components/IssuesTable'
+import { LabelList } from 'components/LabelList'
jest.mock('next/navigation', () => ({
useRouter: () => ({
@@ -47,6 +48,36 @@ jest.mock('@heroui/tooltip', () => ({
},
}))
+interface MockLabelListProps {
+ entityKey: string
+ labels: string[]
+ maxVisible?: number
+ className?: string
+}
+
+const MockLabelList = (props: MockLabelListProps) => {
+ const { entityKey, labels, maxVisible = 5, className } = props
+ if (!labels || labels.length === 0) return null
+ const visibleLabels = labels.slice(0, maxVisible)
+ const remainingCount = labels.length - maxVisible
+ return (
+
+ {visibleLabels.map((label) => (
+
+ {label}
+
+ ))}
+ {remainingCount > 0 && +{remainingCount} more}
+
+ )
+}
+
+jest.mock('components/LabelList', () => ({
+ // Must match the module export name for the mock to be used by IssuesTable
+ // eslint-disable-next-line @typescript-eslint/naming-convention -- component export name
+ LabelList: jest.fn((props: MockLabelListProps) => ),
+}))
+
const mockIssues: IssueRow[] = [
{
objectID: '1',
@@ -102,6 +133,10 @@ describe('', () => {
issues: mockIssues,
}
+ beforeEach(() => {
+ jest.mocked(LabelList).mockClear()
+ })
+
describe('Rendering', () => {
it('renders table view', () => {
render()
@@ -200,6 +235,83 @@ describe('', () => {
render()
expect(screen.getByText('+2 more')).toBeInTheDocument()
})
+
+ it('uses LabelList with entityKey derived from issue objectID', () => {
+ render()
+ expect(LabelList).toHaveBeenCalledTimes(1)
+ expect(LabelList).toHaveBeenCalledWith(
+ expect.objectContaining({
+ entityKey: 'issue-1',
+ labels: ['bug', 'enhancement'],
+ maxVisible: 5,
+ }),
+ undefined
+ )
+ })
+
+ it('passes maxVisibleLabels to LabelList as maxVisible', () => {
+ render()
+ expect(LabelList).toHaveBeenCalledTimes(1)
+ expect(LabelList).toHaveBeenCalledWith(
+ expect.objectContaining({
+ entityKey: 'issue-1',
+ labels: ['bug', 'enhancement'],
+ maxVisible: 3,
+ }),
+ undefined
+ )
+ })
+
+ it('passes empty array to LabelList when issue has no labels', () => {
+ render()
+ expect(LabelList).toHaveBeenCalledTimes(1)
+ expect(LabelList).toHaveBeenCalledWith(
+ expect.objectContaining({
+ entityKey: 'issue-3',
+ labels: [],
+ maxVisible: 5,
+ }),
+ undefined
+ )
+ })
+
+ it('passes empty array to LabelList when issue.labels is undefined', () => {
+ const issueWithUndefinedLabels = {
+ ...mockIssues[0],
+ objectID: 'undefined-labels',
+ labels: undefined,
+ } as IssueRow
+ render()
+ expect(LabelList).toHaveBeenCalledTimes(1)
+ expect(LabelList).toHaveBeenCalledWith(
+ expect.objectContaining({
+ entityKey: 'issue-undefined-labels',
+ labels: [],
+ maxVisible: 5,
+ }),
+ undefined
+ )
+ })
+
+ it('calls LabelList once per issue row with correct labels', () => {
+ render()
+ expect(LabelList).toHaveBeenCalledTimes(3)
+ expect(LabelList).toHaveBeenNthCalledWith(
+ 1,
+ expect.objectContaining({ entityKey: 'issue-1', labels: ['bug', 'enhancement'] }),
+ undefined
+ )
+ expect(LabelList).toHaveBeenNthCalledWith(
+ 2,
+ expect.objectContaining({ entityKey: 'issue-2', labels: ['documentation'] }),
+ undefined
+ )
+ expect(LabelList).toHaveBeenNthCalledWith(
+ 3,
+ expect.objectContaining({ entityKey: 'issue-3', labels: [] }),
+ undefined
+ )
+ })
})
describe('Assignee Column', () => {
diff --git a/frontend/src/components/IssuesTable.tsx b/frontend/src/components/IssuesTable.tsx
index d0c2f53d97..1e4805ca5e 100644
--- a/frontend/src/components/IssuesTable.tsx
+++ b/frontend/src/components/IssuesTable.tsx
@@ -5,6 +5,8 @@ import Image from 'next/image'
import { useRouter } from 'next/navigation'
import type React from 'react'
+import { LabelList } from 'components/LabelList'
+
export type IssueRow = {
objectID: string
number: number
@@ -141,23 +143,12 @@ const IssuesTable: React.FC = ({
{/* Labels */}
- {issue.labels && issue.labels.length > 0 ? (
-
- {issue.labels.slice(0, maxVisibleLabels).map((label) => (
-
- {label}
-
- ))}
- {issue.labels.length > maxVisibleLabels && (
-
- +{issue.labels.length - maxVisibleLabels} more
-
- )}
-
- ) : null}
+
|
{/* Assignee */}