Skip to content
Merged
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
17 changes: 3 additions & 14 deletions src/components/common/TransactionHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,7 @@ const SAMPLE_TRANSACTIONS: Transaction[] = [
},
];

const formatTimestamp = (timestamp: number) => {
const now = Date.now();
const diff = now - timestamp;
const minutes = Math.floor(diff / (1000 * 60));
const hours = Math.floor(diff / (1000 * 60 * 60));
const days = Math.floor(diff / (1000 * 60 * 60 * 24));

if (minutes < 1) return 'Just now';
if (minutes < 60) return `${minutes}m ago`;
if (hours < 24) return `${hours}h ago`;
return `${days}d ago`;
};
import { formatRelativeTime } from '@/utils/time.utils';

const TransactionHistory: React.FC = () => {
const [isCompact, setIsCompact] = useState(() => {
Expand Down Expand Up @@ -186,7 +175,7 @@ const TransactionHistory: React.FC = () => {
<span className="text-white/30">•</span>
<span>{tx.price} XLM</span>
<span className="text-white/30">•</span>
<span>{formatTimestamp(tx.timestamp)}</span>
<span>{formatRelativeTime(tx.timestamp)}</span>
</div>
)}
</div>
Expand Down Expand Up @@ -256,7 +245,7 @@ const TransactionHistory: React.FC = () => {
<span className="text-white/30">•</span>
<span>{tx.price} XLM</span>
<span className="text-white/30">•</span>
<span>{formatTimestamp(tx.timestamp)}</span>
<span>{formatRelativeTime(tx.timestamp)}</span>
<span className="text-white/30">•</span>
<span>{tx.txHash}</span>
</div>
Expand Down
15 changes: 15 additions & 0 deletions src/components/common/__tests__/TransactionHistory.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,19 @@ describe('TransactionHistory – activity feed sign prefix (integration)', () =>
expect(amountEl!.textContent).toMatch(/XLM$/);
});
});

it('renders relative time label correctly for recent versus older events (#487)', () => {
render(<TransactionHistory />);

// SAMPLE_TRANSACTIONS has one from 30 minutes ago, one from 5 days ago (120 hours).
// We expect the first one to say "30 min ago" and the latter to say "5 days ago".
// Actually, let's just check for 'min ago' and 'days ago'
expect(screen.getAllByText(/min ago/)).not.toHaveLength(0);
expect(screen.getAllByText(/days ago/)).not.toHaveLength(0);

// Ensure raw ISO timestamp is not shown
const isoRegex = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
const rawTimestamps = screen.queryAllByText(isoRegex);
expect(rawTimestamps).toHaveLength(0);
});
});
3 changes: 2 additions & 1 deletion src/components/home/TrendingCreatorCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Link } from 'react-router';
import type { Course } from '@/services/course.service';

type Props = { creator: Course & { walletAddress: string } };
import { formatHolderCount } from '@/utils/numberFormat.utils';

export default function TrendingCreatorCard({ creator }: Props) {
const name = creator.title || 'Unnamed creator';
Expand Down Expand Up @@ -49,7 +50,7 @@ export default function TrendingCreatorCard({ creator }: Props) {
<div className="flex items-center gap-1.5 text-gray-400">
<Users className="size-3.5" />
<span className="font-mono text-[10px]">
{creator.creatorShareSupply.toLocaleString()}
{formatHolderCount(creator.creatorShareSupply)}
</span>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { render, screen } from '@testing-library/react';
import { describe, expect, it } from 'vitest';
import { MemoryRouter } from 'react-router';
import TrendingCreatorCard from '../TrendingCreatorCard';
import type { Course } from '@/services/course.service';

const baseCreator: Course & { walletAddress: string } = {
id: 'test-1',
title: 'Test Creator',
description: 'Test Description',
price: 10,
instructorId: 'user1',
walletAddress: '0x123',
socialHandle: 'test',
category: 'Art',
level: 'Advanced',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
isVerified: false,
status: 'active',
};

describe('TrendingCreatorCard integration (#484)', () => {
it('formats holder count above 1000 with a K suffix', () => {
render(
<MemoryRouter>
<TrendingCreatorCard
creator={{
...baseCreator,
creatorShareSupply: 1500,
}}
/>
</MemoryRouter>
);

expect(screen.getByText('1.5K')).toBeInTheDocument();
expect(screen.queryByText('1,500')).not.toBeInTheDocument();
expect(screen.queryByText('1500')).not.toBeInTheDocument();
});

it('shows the raw number for counts below 1000', () => {
render(
<MemoryRouter>
<TrendingCreatorCard
creator={{
...baseCreator,
creatorShareSupply: 999,
}}
/>
</MemoryRouter>
);

expect(screen.getByText('999')).toBeInTheDocument();
});
});
7 changes: 7 additions & 0 deletions src/hooks/__tests__/useIsMobile.integration.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,11 @@ describe('useIsMobile integration (#485)', () => {
});
expect(screen.getByTestId('mobile-state')).toHaveTextContent('mobile');
});

it('cleans up the media query listener on unmount', () => {
const removeSpy = vi.spyOn(mql, 'removeEventListener');
const { unmount } = render(<MobileProbe />);
unmount();
expect(removeSpy).toHaveBeenCalledWith('change', expect.any(Function));
});
});
Loading