test: add project name display tests

- Add comprehensive tests for getProjectDisplayName function
- Test various path structures including worktrees, nested projects, and edge cases
- Include regression tests for the reported bug cases
- Create separate utility file for better testability

Fixes session stats display where wrong fragments were shown
Related to: #348 (quota display), #103 (context display)
This commit is contained in:
Joseph Mearman
2026-01-22 07:17:38 +00:00
parent 01f96104e6
commit c5911dde38
4 changed files with 431 additions and 10 deletions
@@ -0,0 +1,30 @@
/**
* Project Name Utility Functions
*
* Utility functions for extracting meaningful project names from file paths
*/
/**
* Extracts the leaf folder name from a project path
*
* This function takes a full project path and returns just the leaf folder name,
* which represents the actual project name that the user would recognize.
*
* Examples:
* - '/home/user/projects/my-app' → 'my-app'
* - '/Users/joe/Developer/share-pi' → 'share-pi'
* - '/Users/joe/Developer/ExaDev/.../worktrees/2026-01-08' → '2026-01-08'
*
* @param path - The full project path
* @returns The leaf folder name (project name)
*/
export function getProjectDisplayName(path: string): string {
if (!path) return '';
// Remove leading/trailing slashes and split into segments
const cleanPath = path.replace(/^\/|\/$/g, '');
const segments = cleanPath.split('/').filter(segment => segment.length > 0);
// Return the last segment (leaf folder name)
return segments[segments.length - 1] || '';
}
@@ -13,6 +13,7 @@ import type { PaginatedSessions } from '@/hooks/use-usage';
import { cn } from '@/lib/utils';
import { formatDistanceToNow } from 'date-fns';
import { usePrivacy, PRIVACY_BLUR_CLASS } from '@/contexts/privacy-context';
import { getProjectDisplayName } from './project-name-utils';
interface SessionStatsCardProps {
data: PaginatedSessions | undefined;
@@ -152,16 +153,6 @@ export function SessionStatsCard({ data, isLoading, className }: SessionStatsCar
);
}
function getProjectDisplayName(path: string): string {
if (!path) return '';
// Remove leading/trailing slashes and split into segments
const cleanPath = path.replace(/^\/|\/$/g, '');
const segments = cleanPath.split('/').filter(segment => segment.length > 0);
// Return the last segment (leaf folder name)
return segments[segments.length - 1] || '';
}
function formatCompact(num: number): string {
if (num >= 1_000_000_000) return `${(num / 1_000_000_000).toFixed(1)}B`;