Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
85 changes: 39 additions & 46 deletions frontend/__tests__/unit/components/CalendarButton.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -332,58 +332,51 @@ describe('CalendarButton', () => {
})
})

describe('long title overflow handling', () => {
it('remains accessible with very long event titles', () => {
const longTitle =
'This Is A Very Long Event Title That Extends Beyond Normal Length With Additional Description'
render(
<CalendarButton
event={{
title: longTitle,
startDate: '2026-06-22',
endDate: '2026-06-26',
}}
className="flex-shrink-0"
/>
)
describe('hover state', () => {
it('toggles icon on hover - shows FaCalendarPlus when hovering', async () => {
render(<CalendarButton event={mockEvent} />)
const button = screen.getByRole('button')
expect(button).toBeInTheDocument()
expect(button).toHaveAttribute('aria-label', `Add ${longTitle} to Calendar`)

// Initially should show FaCalendar (not hovered)

// Simulate mouse enter
fireEvent.mouseEnter(button)
Comment thread
anurag2787 marked this conversation as resolved.
await waitFor(() => {
// After hover, FaCalendarPlus should be shown (different SVG)
expect(button).toBeInTheDocument()
})
Comment thread
anurag2787 marked this conversation as resolved.
})

it('maintains visibility with flex-shrink-0 class', () => {
render(
<CalendarButton
event={{
title: 'Very Long Event Title That Could Potentially Cause Overflow Issues',
startDate: '2025-12-01',
}}
className="flex-shrink-0 text-gray-600"
/>
)
it('reverts to FaCalendar icon when mouse leaves', async () => {
render(<CalendarButton event={mockEvent} />)
const button = screen.getByRole('button')
expect(button).toHaveClass('flex-shrink-0')
expect(button).toBeVisible()

// Mouse enter - hover state true
fireEvent.mouseEnter(button)

// Mouse leave - hover state false
fireEvent.mouseLeave(button)

await waitFor(() => {
expect(button).toBeInTheDocument()
})
})
Comment thread
anurag2787 marked this conversation as resolved.

it('works correctly in flex container with long text sibling', () => {
const { container } = render(
<div className="flex items-center justify-between gap-2">
<button className="min-w-0 flex-1 truncate">
This Is A Really Long Event Title That Should Be Truncated Properly
</button>
<CalendarButton
event={{
title: 'Event',
startDate: '2025-12-01',
}}
className="flex-shrink-0"
/>
</div>
)
const button = container.querySelector('button[aria-label="Add Event to Calendar"]')
expect(button).toBeInTheDocument()
expect(button).toHaveClass('flex-shrink-0')
it('maintains button functionality during hover state transitions', async () => {
render(<CalendarButton event={mockEvent} />)
const button = screen.getByRole('button')

fireEvent.mouseEnter(button)
fireEvent.mouseLeave(button)

expect(button).not.toBeDisabled()

fireEvent.click(button)
expect(button).toBeDisabled()

await waitFor(() => {
expect(button).not.toBeDisabled()
})
})
})
})
83 changes: 83 additions & 0 deletions frontend/__tests__/unit/components/Card.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -647,4 +647,87 @@ describe('Card', () => {
expect(screen.queryByTestId('label-more')).not.toBeInTheDocument()
expect(screen.getAllByTestId('label')).toHaveLength(5)
})

describe('timeline rendering', () => {
it('renders timeline when both start and end dates are provided', () => {
const propsWithTimeline = {
...baseProps,
timeline: {
start: '2024-01-01',
end: '2024-12-31',
},
}
render(<Card {...propsWithTimeline} />)
expect(screen.getByTestId('calendar-icon')).toBeInTheDocument()
})

it('does not render timeline when start date is empty string', () => {
const propsWithEmptyStart = {
...baseProps,
timeline: {
start: '',
end: '2024-12-31',
},
}
render(<Card {...propsWithEmptyStart} />)
expect(screen.queryByTestId('calendar-icon')).not.toBeInTheDocument()
})

it('does not render timeline when end date is empty string', () => {
const propsWithEmptyEnd = {
...baseProps,
timeline: {
start: '2024-01-01',
end: '',
},
}
render(<Card {...propsWithEmptyEnd} />)
expect(screen.queryByTestId('calendar-icon')).not.toBeInTheDocument()
})

it('does not render timeline when timeline is undefined', () => {
render(<Card {...baseProps} />)
expect(screen.queryByTestId('calendar-icon')).not.toBeInTheDocument()
})
})

describe('social media aria-label fallback', () => {
it('uses item title as aria-label when provided', () => {
const propsWithSocialTitle = {
...baseProps,
social: [
{ title: 'GitHub Profile', url: 'https://github.com/test', icon: MockIcon as IconType },
],
}
render(<Card {...propsWithSocialTitle} />)
const socialLink = screen.getByRole('link', { name: 'GitHub Profile' })
expect(socialLink).toHaveAttribute('aria-label', 'GitHub Profile')
})

it('uses fallback aria-label when item title is empty', () => {
const propsWithEmptySocialTitle = {
...baseProps,
social: [{ title: '', url: 'https://github.com/test', icon: MockIcon as IconType }],
}
render(<Card {...propsWithEmptySocialTitle} />)
const socialLink = screen.getByRole('link', { name: 'Social media link' })
expect(socialLink).toHaveAttribute('aria-label', 'Social media link')
})

it('uses fallback aria-label when item title is undefined', () => {
const propsWithUndefinedSocialTitle = {
...baseProps,
social: [
{
title: undefined as unknown as string,
url: 'https://github.com/test',
icon: MockIcon as IconType,
},
],
}
render(<Card {...propsWithUndefinedSocialTitle} />)
const socialLink = screen.getByRole('link', { name: 'Social media link' })
expect(socialLink).toHaveAttribute('aria-label', 'Social media link')
})
})
})
Loading