diff --git a/frontend/src/components/ConversionUpload/ConversionUploadEnhanced.test.tsx b/frontend/src/components/ConversionUpload/ConversionUploadEnhanced.test.tsx index 93859a12..bf38d843 100644 --- a/frontend/src/components/ConversionUpload/ConversionUploadEnhanced.test.tsx +++ b/frontend/src/components/ConversionUpload/ConversionUploadEnhanced.test.tsx @@ -4,6 +4,7 @@ import userEvent from '@testing-library/user-event'; import { ConversionUploadEnhanced } from './ConversionUploadEnhanced'; import { describe, test, expect, vi } from 'vitest'; import { convertMod } from '../../services/api'; +import { ProgressProvider } from '../../contexts/ProgressContext'; // Mock the API calls vi.mock('../../services/api', () => ({ @@ -17,16 +18,21 @@ vi.mock('../../services/api', () => ({ // Mock the WebSocket service vi.mock('../../services/websocket', () => ({ createConversionWebSocket: vi.fn(() => ({ - onStatus: vi.fn(), - onMessage: vi.fn(), + onStatus: vi.fn(() => vi.fn()), + onMessage: vi.fn(() => vi.fn()), connect: vi.fn(), destroy: vi.fn(), + disconnect: vi.fn(), })), })); describe('ConversionUploadEnhanced Accessibility', () => { test('Smart Assumptions info button has correct accessibility attributes', () => { - render(); + render( + + + + ); // Find the info button const infoButton = screen.getByText('?'); @@ -52,7 +58,11 @@ describe('ConversionUploadEnhanced Accessibility', () => { test('Remove file button has accessible name', async () => { const user = userEvent.setup(); - render(); + render( + + + + ); // Upload a file const file = new File(['dummy content'], 'test-mod.jar', { type: 'application/java-archive' }); @@ -74,7 +84,11 @@ describe('ConversionUploadEnhanced Accessibility', () => { test('Error message has role="alert"', async () => { const user = userEvent.setup(); - render(); + render( + + + + ); // Trigger an error via invalid URL const urlInput = screen.getByPlaceholderText(/curseforge/i); @@ -89,14 +103,22 @@ describe('ConversionUploadEnhanced Accessibility', () => { }); test('URL input has an accessible label', () => { - render(); + render( + + + + ); const urlInput = screen.getByLabelText('Modpack URL'); expect(urlInput).toBeInTheDocument(); }); test('Button shows spinner when processing', async () => { const user = userEvent.setup(); - render(); + render( + + + + ); // Check initial button text const submitButton = screen.getByText('Upload & Convert'); diff --git a/frontend/src/components/ConversionUpload/ConversionUploadEnhanced.tsx b/frontend/src/components/ConversionUpload/ConversionUploadEnhanced.tsx index af7a1bbf..4b7d3b05 100644 --- a/frontend/src/components/ConversionUpload/ConversionUploadEnhanced.tsx +++ b/frontend/src/components/ConversionUpload/ConversionUploadEnhanced.tsx @@ -14,6 +14,7 @@ import { ConversionStatusEnum } from '../../types/api'; import ConversionProgress from '../ConversionProgress/ConversionProgress'; +import { formatFileSize } from '../../utils/formatters'; import './ConversionUpload.css'; // Configuration constants @@ -410,6 +411,12 @@ export const ConversionUploadEnhanced: React.FC = ({ const isCancelled = currentStatus?.status === ConversionStatusEnum.CANCELLED; const isFinished = isCompleted || isFailed || isCancelled; + const getFileIcon = (fileName: string) => { + if (fileName.toLowerCase().endsWith('.jar')) return '☕'; + if (fileName.toLowerCase().endsWith('.zip')) return '🗜️'; + return '📦'; + }; + return ( Convert Your Modpack @@ -442,10 +449,10 @@ export const ConversionUploadEnhanced: React.FC = ({ ) : selectedFile ? ( - 📦 + {getFileIcon(selectedFile.name)} {selectedFile.name} - {(selectedFile.size / 1024 / 1024).toFixed(2)} MB + {formatFileSize(selectedFile.size)} {getStatusMessage()} = ({ ) : ( - ☁️ - Drag & drop your modpack here + ☁️ + {isDragActive ? "Drop file to upload 📂" : "Drag & drop your modpack here"} { + if (bytes === 0) return '0 Bytes'; + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f0dfb02b..8fa90f9a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -148,7 +148,7 @@ importers: specifier: ^3.8.1 version: 3.8.1 storybook: - specifier: ^10.2.9 + specifier: ^10.2.10 version: 10.2.10(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) typescript: specifier: ^5.9.3 diff --git a/verification_jar.png b/verification_jar.png new file mode 100644 index 00000000..73826892 Binary files /dev/null and b/verification_jar.png differ diff --git a/verification_zip.png b/verification_zip.png new file mode 100644 index 00000000..6014bd49 Binary files /dev/null and b/verification_zip.png differ