From 7d5c48c2a810dd8b869bec9145c5cc83c7ebc875 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Sat, 14 Feb 2026 18:25:11 +0100 Subject: [PATCH] Add unit and E2E tests for all panel components - Vitest tests for Sidebar, NoteList, Inspector (7 tests) - Playwright E2E tests verifying four-panel layout renders (2 tests) - All tests passing: cargo test (10), pnpm test (7), pnpm test:e2e (2) Co-Authored-By: Claude Opus 4.6 --- e2e/app.spec.ts | 18 +++++++++++++++ playwright.config.ts | 14 ++++++++++++ src/components/Inspector.test.tsx | 25 ++++++++++++++++++++ src/components/NoteList.test.tsx | 38 +++++++++++++++++++++++++++++++ src/components/Sidebar.test.tsx | 18 +++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 e2e/app.spec.ts create mode 100644 playwright.config.ts create mode 100644 src/components/Inspector.test.tsx create mode 100644 src/components/NoteList.test.tsx create mode 100644 src/components/Sidebar.test.tsx diff --git a/e2e/app.spec.ts b/e2e/app.spec.ts new file mode 100644 index 00000000..200535d3 --- /dev/null +++ b/e2e/app.spec.ts @@ -0,0 +1,18 @@ +import { test, expect } from '@playwright/test' + +test('app loads with four-panel layout', async ({ page }) => { + await page.goto('/') + + // Verify the four panels are present + await expect(page.locator('.sidebar')).toBeVisible() + await expect(page.locator('.note-list')).toBeVisible() + await expect(page.locator('.editor')).toBeVisible() + await expect(page.locator('.inspector')).toBeVisible() +}) + +test('sidebar shows navigation items', async ({ page }) => { + await page.goto('/') + + await expect(page.getByText('Laputa')).toBeVisible() + await expect(page.getByText('All Notes')).toBeVisible() +}) diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 00000000..7d19bae7 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from '@playwright/test' + +export default defineConfig({ + testDir: './e2e', + timeout: 30000, + use: { + baseURL: 'http://localhost:5173', + }, + webServer: { + command: 'pnpm dev', + port: 5173, + reuseExistingServer: true, + }, +}) diff --git a/src/components/Inspector.test.tsx b/src/components/Inspector.test.tsx new file mode 100644 index 00000000..2a5bc7be --- /dev/null +++ b/src/components/Inspector.test.tsx @@ -0,0 +1,25 @@ +import { render, screen, fireEvent } from '@testing-library/react' +import { describe, it, expect, vi } from 'vitest' +import { Inspector } from './Inspector' + +describe('Inspector', () => { + it('renders expanded state with sections', () => { + render( {}} />) + expect(screen.getByText('Inspector')).toBeInTheDocument() + expect(screen.getByText('Properties')).toBeInTheDocument() + expect(screen.getByText('Relationships')).toBeInTheDocument() + }) + + it('renders collapsed state without sections', () => { + render( {}} />) + expect(screen.queryByText('Inspector')).not.toBeInTheDocument() + expect(screen.queryByText('Properties')).not.toBeInTheDocument() + }) + + it('calls onToggle when toggle button clicked', () => { + const onToggle = vi.fn() + render() + fireEvent.click(screen.getByRole('button')) + expect(onToggle).toHaveBeenCalledOnce() + }) +}) diff --git a/src/components/NoteList.test.tsx b/src/components/NoteList.test.tsx new file mode 100644 index 00000000..fcc0d852 --- /dev/null +++ b/src/components/NoteList.test.tsx @@ -0,0 +1,38 @@ +import { render, screen } from '@testing-library/react' +import { describe, it, expect } from 'vitest' +import { NoteList } from './NoteList' + +describe('NoteList', () => { + it('shows empty state when no entries', () => { + render() + expect(screen.getByText('No notes loaded')).toBeInTheDocument() + expect(screen.getByText('0')).toBeInTheDocument() + }) + + it('renders note entries', () => { + const entries = [ + { + path: '/vault/note1.md', + filename: 'note1.md', + title: 'First Note', + isA: 'Project', + status: 'Active', + modifiedAt: 1700000000, + }, + { + path: '/vault/note2.md', + filename: 'note2.md', + title: 'Second Note', + isA: null, + status: null, + modifiedAt: null, + }, + ] + render() + expect(screen.getByText('First Note')).toBeInTheDocument() + expect(screen.getByText('Second Note')).toBeInTheDocument() + expect(screen.getByText('Project')).toBeInTheDocument() + expect(screen.getByText('Active')).toBeInTheDocument() + expect(screen.getByText('2')).toBeInTheDocument() + }) +}) diff --git a/src/components/Sidebar.test.tsx b/src/components/Sidebar.test.tsx new file mode 100644 index 00000000..b6739c1f --- /dev/null +++ b/src/components/Sidebar.test.tsx @@ -0,0 +1,18 @@ +import { render, screen } from '@testing-library/react' +import { describe, it, expect } from 'vitest' +import { Sidebar } from './Sidebar' + +describe('Sidebar', () => { + it('renders the app title', () => { + render() + expect(screen.getByText('Laputa')).toBeInTheDocument() + }) + + it('renders navigation items', () => { + render() + expect(screen.getByText('All Notes')).toBeInTheDocument() + expect(screen.getByText('Projects')).toBeInTheDocument() + expect(screen.getByText('Tasks')).toBeInTheDocument() + expect(screen.getByText('People')).toBeInTheDocument() + }) +})