diff --git a/apps/web/package.json b/apps/web/package.json index fe97c66a..a794741d 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -7,8 +7,6 @@ "dev": "next dev --turbopack", "build": "next build", "start": "next start", - "test": "vitest", - "test:run": "vitest run", "lint": "biome check src/", "lint:fix": "biome check src/ --write", "format": "biome format src/ --write", @@ -76,9 +74,6 @@ "devDependencies": { "@tailwindcss/postcss": "^4.1.11", "@tailwindcss/typography": "^0.5.16", - "@testing-library/jest-dom": "^6.4.0", - "@testing-library/react": "^15.0.7", - "@testing-library/user-event": "^14.5.2", "@types/bun": "latest", "@types/node": "^24.2.1", "@types/pg": "^8.15.4", @@ -86,11 +81,9 @@ "@types/react-dom": "^18.2.18", "cross-env": "^7.0.3", "drizzle-kit": "^0.31.4", - "jsdom": "^26.0.0", "postcss": "^8", "tailwindcss": "^4.1.11", "tsx": "^4.7.1", - "typescript": "^5.8.3", - "vitest": "^2.1.8" + "typescript": "^5.8.3" } } diff --git a/apps/web/src/components/editor/timeline/__tests__/TimelineToolbar.test.tsx b/apps/web/src/components/editor/timeline/__tests__/TimelineToolbar.test.tsx deleted file mode 100644 index 9a8ef666..00000000 --- a/apps/web/src/components/editor/timeline/__tests__/TimelineToolbar.test.tsx +++ /dev/null @@ -1,217 +0,0 @@ -import React from 'react' -import { describe, it, expect, vi, beforeEach } from 'vitest' -import { render, screen, fireEvent } from '@testing-library/react' -import { Timeline } from '../index' - -// Mock the stores and hooks -vi.mock('@/stores/timeline-store', () => ({ - useTimelineStore: () => ({ - tracks: [], - addTrack: vi.fn(), - addElementToTrack: vi.fn(), - removeElementFromTrack: vi.fn(), - removeElementFromTrackWithRipple: vi.fn(), - selectedElements: [], - clearSelectedElements: vi.fn(), - splitElement: vi.fn(), - splitAndKeepLeft: vi.fn(), - splitAndKeepRight: vi.fn(), - separateAudio: vi.fn(), - snappingEnabled: false, - toggleSnapping: vi.fn(), - deleteElements: vi.fn(), - duplicateElement: vi.fn(), - selectAll: vi.fn(), - zoomLevel: 1, - setZoomLevel: vi.fn(), - dragState: { isDragging: false, draggedElement: null, dragOffset: { x: 0, y: 0 } }, - getTotalDuration: () => 100, - setSelectedElements: vi.fn(), - toggleTrackMute: vi.fn(), - }) -})) - -vi.mock('@/stores/media-store', () => ({ - useMediaStore: () => ({ - mediaItems: [], - addMediaItem: vi.fn(), - }) -})) - -vi.mock('@/stores/project-store', () => ({ - useProjectStore: () => ({ - activeProject: null, - }) -})) - -const mockSeek = vi.fn() - -vi.mock('@/stores/playback-store', () => ({ - usePlaybackStore: () => ({ - currentTime: 0, - duration: 100, - seek: mockSeek, - setDuration: vi.fn(), - isPlaying: false, - toggle: vi.fn(), - }), -})) - -// Mock the timeline playhead hook -vi.mock('@/hooks/use-timeline-playhead', () => ({ - useTimelinePlayhead: () => ({ - playheadRef: { current: null }, - updatePlayheadPosition: vi.fn(), - onPlayheadDrag: vi.fn(), - }) -})) - -vi.mock('@/hooks/use-editor-actions', () => ({ - useEditorActions: () => ({}) -})) - -vi.mock('@/hooks/use-timeline-context-menu', () => ({ - useTimelineContextMenu: () => ({ - contextMenu: null, - handleContextMenu: vi.fn(), - closeContextMenu: vi.fn(), - }) -})) - -vi.mock('@/hooks/use-timeline-selection', () => ({ - useTimelineSelection: () => ({ - isSelecting: false, - selectionBox: null, - handleMouseDown: vi.fn(), - }) -})) - -vi.mock('@/hooks/use-timeline-drag-drop', () => ({ - useTimelineDragDrop: () => ({ - dragProps: {}, - }) -})) - -// Mock UI components to avoid dependency issues -vi.mock('../../ui/tooltip', () => ({ - Tooltip: ({ children }: any) => children, - TooltipTrigger: ({ children }: any) => children, - TooltipContent: ({ children }: any) =>
{children}
, - TooltipProvider: ({ children }: any) => children, -})) - -vi.mock('../../ui/button', () => ({ - Button: ({ children, onClick, ...props }: any) => ( - - ), -})) - -vi.mock('../../ui/scroll-area', () => ({ - ScrollArea: ({ children }: any) =>
{children}
, -})) - -vi.mock('lucide-react', () => ({ - SkipBack: () => , - Play: () => , - Pause: () => , - Scissors: () => , - ArrowLeftToLine: () => , - ArrowRightToLine: () => , - Trash2: () => , - Snowflake: () => , - Copy: () => , - SplitSquareHorizontal: () => , - Video: () => , - Music: () => , - TypeIcon: () => , - Magnet: () => , - Link: () => , - ZoomIn: () => , - ZoomOut: () => , -})) - -vi.mock('@/constants/timeline', () => ({ - TIMELINE_CONSTANTS: { - DEFAULT_TEXT_DURATION: 5, - } -})) - -vi.mock('@/lib/utils', () => ({ - cn: (...args: any[]) => args.join(' '), - snapTimeToFrame: (time: number) => time, -})) - -// Mock timeline utilities -vi.mock('@/lib/timeline-utils', () => ({ - getTotalDuration: () => 100, - getCurrentSnapPoint: () => null, -})) - -// Mock context menu components -vi.mock('../../ui/context-menu', () => ({ - ContextMenu: ({ children }: any) => children, - ContextMenuTrigger: ({ children }: any) => children, - ContextMenuContent: ({ children }: any) =>
{children}
, - ContextMenuItem: ({ children }: any) =>
{children}
, - ContextMenuSeparator: () =>
, -})) - -// Mock dialog components -vi.mock('../../ui/dialog', () => ({ - Dialog: ({ children }: any) => children, - DialogContent: ({ children }: any) =>
{children}
, - DialogHeader: ({ children }: any) =>
{children}
, - DialogTitle: ({ children }: any) =>
{children}
, -})) - -describe('Timeline - Return to Start Button', () => { - beforeEach(() => { - mockSeek.mockClear() - }) - - it('should render Return to Start button', () => { - render() - - // Look for the SkipBack icon which indicates our button - const skipBackIcon = screen.getByTestId('skip-back-icon') - expect(skipBackIcon).toBeInTheDocument() - }) - - it('should call seek(0) when Return to Start button is clicked', () => { - render() - - // Find the button that contains the SkipBack icon - const skipBackIcon = screen.getByTestId('skip-back-icon') - const button = skipBackIcon.closest('button') - - expect(button).toBeInTheDocument() - fireEvent.click(button!) - - expect(mockSeek).toHaveBeenCalledWith(0) - }) - - it('should have tooltip structure for Return to Start button', () => { - render() - - // Find the skip back button and verify it's wrapped in tooltip components - const skipBackIcon = screen.getByTestId('skip-back-icon') - const button = skipBackIcon.closest('button') - - expect(button).toBeInTheDocument() - // The button should exist and be clickable, which means the tooltip structure is in place - expect(button).toHaveAttribute('data-state', 'closed') // Tooltip trigger state - }) - - it('should have SkipBack icon in Return to Start button', () => { - render() - - const skipBackIcon = screen.getByTestId('skip-back-icon') - expect(skipBackIcon).toBeInTheDocument() - - // Verify it's inside a button - const button = skipBackIcon.closest('button') - expect(button).toBeInTheDocument() - }) -}) \ No newline at end of file diff --git a/apps/web/src/components/editor/timeline/index.tsx b/apps/web/src/components/editor/timeline/index.tsx index 669d556c..d8261d9b 100644 --- a/apps/web/src/components/editor/timeline/index.tsx +++ b/apps/web/src/components/editor/timeline/index.tsx @@ -1,6 +1,5 @@ "use client"; -import React from "react"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Button } from "../../ui/button"; import { @@ -609,7 +608,11 @@ export function Timeline() { onMouseEnter={() => setIsInTimeline(true)} onMouseLeave={() => setIsInTimeline(false)} > - + {/* Timeline Container */}
{ if (selectedElements.length === 0) return; let splitCount = 0; @@ -1075,7 +1077,6 @@ function TimelineToolbar({ clearSelectedElements(); }; - // Zoom handlers const handleZoomIn = () => { setZoomLevel(Math.min(4, zoomLevel + 0.25)); }; @@ -1092,13 +1093,11 @@ function TimelineToolbar({ await toggleBookmark(currentTime); }; - // Check if the current time is bookmarked const currentBookmarked = isBookmarked(currentTime); return (
- {/* Play/Pause Button */} - - Return to Start (Home / Enter) - + Return to Start (Home / Enter)
- {/* Time Display */}
{currentTime.toFixed(1)}s / {duration.toFixed(1)}s
- {/* Test Clip Button - for debugging */} {tracks.length === 0 && ( <>
diff --git a/apps/web/src/components/editor/timeline/timeline-playhead.tsx b/apps/web/src/components/editor/timeline/timeline-playhead.tsx index 48c60596..a1be5b26 100644 --- a/apps/web/src/components/editor/timeline/timeline-playhead.tsx +++ b/apps/web/src/components/editor/timeline/timeline-playhead.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useRef, useState, useEffect } from "react"; +import { useRef, useState, useEffect } from "react"; import { TimelineTrack } from "@/types/timeline"; import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants"; import { useTimelinePlayhead } from "@/hooks/use-timeline-playhead"; diff --git a/apps/web/src/hooks/__tests__/use-keyboard-shortcuts-help.test.ts b/apps/web/src/hooks/__tests__/use-keyboard-shortcuts-help.test.ts deleted file mode 100644 index 52c7dcd6..00000000 --- a/apps/web/src/hooks/__tests__/use-keyboard-shortcuts-help.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { describe, it, expect, beforeEach } from 'vitest' -import { renderHook } from '@testing-library/react' -import { useKeyboardShortcutsHelp } from '../use-keyboard-shortcuts-help' -import { useKeybindingsStore } from '../../stores/keybindings-store' - -describe('useKeyboardShortcutsHelp', () => { - beforeEach(() => { - // Reset store to default state before each test - useKeybindingsStore.getState().resetToDefaults() - }) - - it('should format Enter key correctly in shortcuts', () => { - const { result } = renderHook(() => useKeyboardShortcutsHelp()) - - // Find the goto-start action in shortcuts - const gotoStartShortcut = result.current.shortcuts.find( - shortcut => shortcut.action === 'goto-start' - ) - - expect(gotoStartShortcut).toBeDefined() - expect(gotoStartShortcut?.keys).toContain('Enter') - expect(gotoStartShortcut?.keys).toContain('Home') - }) - - it('should include goto-start action with correct description', () => { - const { result } = renderHook(() => useKeyboardShortcutsHelp()) - - const gotoStartShortcut = result.current.shortcuts.find( - shortcut => shortcut.action === 'goto-start' - ) - - expect(gotoStartShortcut).toBeDefined() - expect(gotoStartShortcut?.description).toBe('Go to timeline start') - expect(gotoStartShortcut?.category).toBe('Navigation') - }) - - it('should have multiple keys for goto-start action', () => { - const { result } = renderHook(() => useKeyboardShortcutsHelp()) - - const gotoStartShortcut = result.current.shortcuts.find( - shortcut => shortcut.action === 'goto-start' - ) - - expect(gotoStartShortcut?.keys.length).toBeGreaterThanOrEqual(2) - }) -}) \ No newline at end of file diff --git a/apps/web/src/hooks/use-keyboard-shortcuts-help.ts b/apps/web/src/hooks/use-keyboard-shortcuts-help.ts index 98810cb1..e2cde3b4 100644 --- a/apps/web/src/hooks/use-keyboard-shortcuts-help.ts +++ b/apps/web/src/hooks/use-keyboard-shortcuts-help.ts @@ -77,7 +77,7 @@ const formatKey = (key: string): string => { .replace("down", "↓") .replace("space", "Space") .replace("home", "Home") - .replace("enter", "Enter") // Format Enter key for display in help dialog + .replace("enter", "Enter") .replace("end", "End") .replace("delete", "Delete") .replace("backspace", "Backspace") diff --git a/apps/web/src/stores/keybindings-store.ts b/apps/web/src/stores/keybindings-store.ts index 740a5855..4c11cfde 100644 --- a/apps/web/src/stores/keybindings-store.ts +++ b/apps/web/src/stores/keybindings-store.ts @@ -17,7 +17,7 @@ export const defaultKeybindings: KeybindingConfig = { "shift+left": "jump-backward", "shift+right": "jump-forward", home: "goto-start", - enter: "goto-start", // More intuitive alternative to Home key for timeline navigation + enter: "goto-start", end: "goto-end", s: "split-element", n: "toggle-snapping", diff --git a/apps/web/src/test/setup.ts b/apps/web/src/test/setup.ts deleted file mode 100644 index e53f09dd..00000000 --- a/apps/web/src/test/setup.ts +++ /dev/null @@ -1,8 +0,0 @@ -import '@testing-library/jest-dom' - -// Mock ResizeObserver -global.ResizeObserver = class ResizeObserver { - observe() {} - unobserve() {} - disconnect() {} -} \ No newline at end of file diff --git a/apps/web/vitest.config.ts b/apps/web/vitest.config.ts deleted file mode 100644 index cb1133fb..00000000 --- a/apps/web/vitest.config.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { defineConfig } from 'vitest/config' -import { resolve } from 'path' - -export default defineConfig({ - test: { - environment: 'jsdom', - setupFiles: ['./src/test/setup.ts'], - globals: true, - }, - resolve: { - alias: { - '@': resolve(__dirname, './src'), - }, - }, -}) \ No newline at end of file