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
4 changes: 2 additions & 2 deletions src/components/DriveNavigableItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { items } from '@internxt/lib';
import { CaretRight } from 'phosphor-react-native';
import prettysize from 'prettysize';
import React from 'react';
import { TouchableHighlight, View } from 'react-native';
import { useTailwind } from 'tailwind-rn';
import { FolderIcon, getFileTypeIcon } from '../../helpers';
import { getDisplayName } from '../../helpers/itemNames';
import useGetColor from '../../hooks/useColor';
import globalStyle from '../../styles/global';
import { DriveNavigableItemProps } from '../../types/drive';
Expand Down Expand Up @@ -54,7 +54,7 @@ const DriveNavigableItem: React.FC<DriveNavigableItemProps> = ({ isLoading, disa
numberOfLines={1}
ellipsizeMode={'middle'}
>
{items.getItemDisplayName(props.data)}
{getDisplayName(props.data)}
</AppText>

<AppText style={[tailwind('text-xs'), { color: getColor('text-gray-50') }]}>
Expand Down
321 changes: 321 additions & 0 deletions src/helpers/itemNames.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
import { DriveItemDataProps } from '../types/drive';
import { getDisplayName } from './itemNames';

describe('getDisplayName', () => {
describe('Folders', () => {
it('should return the folder name as-is', () => {
const folder = {
id: 1,
name: 'Documents',
isFolder: true,
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(folder)).toBe('Documents');
});

it('should handle folder names with special characters', () => {
const folder: DriveItemDataProps = {
id: 1,
name: 'My Folder (2024)',
isFolder: true,
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(folder)).toBe('My Folder (2024)');
}) as unknown as DriveItemDataProps;

it('should handle folder names with dots', () => {
const folder: DriveItemDataProps = {
id: 1,
name: 'backup.2024',
isFolder: true,
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(folder)).toBe('backup.2024');
});
});

describe('Files without extension in name', () => {
it('should append the extension to the file name', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'report',
type: 'pdf',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('report.pdf');
});

it('should handle different file extensions', () => {
const cases = [
{ name: 'image', type: 'jpg', expected: 'image.jpg' },
{ name: 'document', type: 'docx', expected: 'document.docx' },
{ name: 'video', type: 'mp4', expected: 'video.mp4' },
{ name: 'data', type: 'json', expected: 'data.json' },
];

cases.forEach(({ name, type, expected }) => {
const file: DriveItemDataProps = {
id: 1,
name,
type,
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe(expected);
});
});
});

describe('Files with extension already in name', () => {
it('should not duplicate the extension if already present', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'report.pdf',
type: 'pdf',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('report.pdf');
});

it('should handle case-insensitive extension matching', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'Image.JPG',
type: 'jpg',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('Image.JPG');
});

it('should handle files with multiple dots in name', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'backup.2024.01.15.tar',
type: 'tar',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('backup.2024.01.15.tar');
});

it('should not append extension if name ends with it in mixed case', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'document.PDF',
type: 'pdf',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('document.PDF');
});
});

describe('Files without type', () => {
it('should return the name as-is when type is undefined', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'unknown',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('unknown');
});

it('should return the name as-is when type is null', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'noextension',
type: undefined,
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('noextension');
});

it('should preserve existing extension in name when type is undefined', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'file.txt',
type: undefined,
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('file.txt');
});
});

describe('Edge cases', () => {
it('should handle empty type string', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'file',
type: '',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('file');
});

it('should handle type with leading/trailing whitespace', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'document',
type: ' pdf ',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('document. pdf ');
});

it('should handle files with dots but different extension', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'archive.tar',
type: 'gz',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('archive.tar.gz');
});

it('should handle numeric extensions', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'file',
type: '001',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('file.001');
});

it('should handle special characters in extension', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'document',
type: 'pdf~',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('document.pdf~');
});

it('should handle very long extensions', () => {
const longExtension = 'verylongextensionname';
const file: DriveItemDataProps = {
id: 1,
name: 'file',
type: longExtension,
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe(`file.${longExtension}`);
});
});

describe('Real-world scenarios', () => {
it('should handle common document files', () => {
const scenarios = [
{ name: 'Meeting Notes', type: 'docx', expected: 'Meeting Notes.docx' },
{ name: 'Budget 2024', type: 'xlsx', expected: 'Budget 2024.xlsx' },
{ name: 'Presentation', type: 'pptx', expected: 'Presentation.pptx' },
];

scenarios.forEach(({ name, type, expected }) => {
const file: DriveItemDataProps = {
id: 1,
name,
type,
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe(expected);
});
});

it('should handle compressed archives with double extensions', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'backup.tar',
type: 'gz',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('backup.tar.gz');
});

it('should handle versioned files', () => {
const file: DriveItemDataProps = {
id: 1,
name: 'document.v2',
type: 'pdf',
isFolder: false,
fileId: 'file-1',
updatedAt: '2025-01-01',
createdAt: '2025-01-01',
} as unknown as DriveItemDataProps;

expect(getDisplayName(file)).toBe('document.v2.pdf');
});
});
});
41 changes: 41 additions & 0 deletions src/helpers/itemNames.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { DriveItemDataProps } from '../types/drive';

/**
* Generates a display name for a drive item (file or folder).
* For folders, returns the name as-is.
* For files, appends the extension if it's not already present in the name.
*
* @param {DriveItemDataProps} item - The drive item (file or folder)
* @returns {string} The formatted display name
*
* @example
* // Folder
* getDisplayName({ name: 'Documents', isFolder: true }) // 'Documents'
*
* @example
* // File without extension in name
* getDisplayName({ name: 'report', type: 'pdf', isFolder: false }) // 'report.pdf'
*
* @example
* // File with extension already in name
* getDisplayName({ name: 'report.pdf', type: 'pdf', isFolder: false }) // 'report.pdf'
*
* @example
* // File without type
* getDisplayName({ name: 'unknown', isFolder: false }) // 'unknown'
*/
export const getDisplayName = (item: DriveItemDataProps): string => {
if (item.isFolder || !item.type) {
return item.name;
}

const normalizedExtension = item.type.trim().toLowerCase();
const normalizedName = item.name.toLowerCase();

const expectedEnding = `.${normalizedExtension}`;
if (normalizedName.endsWith(expectedEnding)) {
return item.name;
}

return `${item.name}.${item.type}`;
};
Loading