diff --git a/.env.example b/.env.example index 2163a83..328f9d8 100644 --- a/.env.example +++ b/.env.example @@ -1,20 +1,38 @@ +# Supabase (required) NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321 NEXT_PUBLIC_SUPABASE_ANON_KEY=get-from-supabase-status -SUPABASE_SERVICE_ROLE_KEY=get-from-supabase-start -RESEND_API_KEY=optional-for-prod -EMAIL_FROM=pulse@pulse.dev +SUPABASE_SERVICE_ROLE_KEY=get-from-supabase-status + +# App NEXT_PUBLIC_APP_URL=http://localhost:3000 -NEXT_PUBLIC_GOOGLE_CLIENT_ID=get-from-google-oauth-client-id +NEXT_PUBLIC_COMPANY_EMAIL_DOMAIN=yourcompany.com +HR_EMAIL=hr@yourcompany.com + +# Auth / tokens TEST_USER_PASSWORD=Test123! JWT_SECRET=your-secure-secret CRON_SECRET=your-secure-random-string -NEXT_PUBLIC_COMPANY_EMAIL_DOMAIN=yourcompany.com -BEDROCK_AWS_ACCESS_KEY_ID -BEDROCK_AWS_SECRET_ACCESS_KEY +ALLOWED_CORS_DOMAIN_SUFFIX=localhost,127.0.0.1 + +# Email +RESEND_API_KEY=optional-for-prod +EMAIL_FROM=pulse@pulse.dev +NEXT_PUBLIC_ENABLE_EMAILS=false + +# AI (AWS Bedrock) +BEDROCK_AWS_ACCESS_KEY_ID= +BEDROCK_AWS_SECRET_ACCESS_KEY= BEDROCK_MODEL_ID=us.anthropic.claude-3-5-haiku-20241022-v1:0 +BEDROCK_AWS_REGION=us-east-1 + +# LangSmith (optional) LANGSMITH_TRACING=true LANGSMITH_ENDPOINT="https://api.smith.langchain.com" LANGSMITH_API_KEY= LANGSMITH_PROJECT="weekly-pulse-app" -ALLOWED_CORS_DOMAIN_SUFFIX=localhost,127.0.0.1 -CODERPUSH_PULSE_SECRET_KEY=your-secret-key \ No newline at end of file + +# Integrations / misc +CODERPUSH_PULSE_SECRET_KEY=your-secret-key + +# Analytics +NEXT_PUBLIC_GA_ID= diff --git a/AGENTS.md b/AGENTS.md index 4bd0167..7cab484 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,44 +1,50 @@ # AGENTS Instructions -This repository contains a Next.js 15 web application called **Pulse**. It uses Supabase for authentication and database storage, Tailwind CSS for styling, and shadcn/ui components. - -Codex should also read `CLAUDE.md` in the repository root for extended architecture and workflow details. +Pulse is a Next.js 15 App Router app (React 19, TypeScript, Tailwind 4) with Supabase and AI features via CopilotKit + AWS Bedrock. ## Scope -These instructions apply to the entire repository. - -## Development Guidelines -- Use TypeScript for all source code. -- Prefer functional React components and hooks. -- Use the utility `cn` from `src/lib/utils.ts` to compose CSS class names. -- UI components should follow the shadcn/ui style (see `components.json`). -- Keep new code and tests within the `src/` directory structure. -- Start the development server with `pnpm dev` and build with `pnpm build`. -- Manage Supabase locally with: - - `supabase start` – start local instance - - `supabase stop` – stop local instance - - `supabase status` – check status - - `supabase db reset` – reset database **(destroys local data, confirm before running)** - -## Linting and Formatting -- Run `pnpm lint` before committing to ensure ESLint rules pass. - -## Testing -- Unit tests use **Vitest**. Run them with `pnpm test:run`. -- End-to-end tests use **Playwright** and require a local Supabase instance and the MCP server. Run them with `pnpm test:e2e`. -- Additional helpers: `pnpm test:e2e:debug` and `pnpm test:coverage`. -- If tests fail due to environment limitations (e.g. missing dependencies), note this in the PR. - -## Commit Messages -Use short descriptive commit messages, for example: -``` -feat: add weekly submission API -docs: update README with setup steps -``` - -## Additional Notes -- E2E tests must drive the browser via the MCP server as described in `docs/prompt-work-with-playwright-mcp.md`. -- For Supabase-related tests, see `docs/supabase-in-test.md` for the hybrid approach using mocks and a local instance. -- Consult `docs/test-plan.md` and `docs/implementation.md` for deeper explanations. -- `CLAUDE.md` contains extended documentation for human contributors. -- Keep documentation updates in the `docs/` directory when adding new features. +Applies to the entire repository. + +## Commands +- `pnpm dev` (Turbopack) +- `pnpm build` +- `pnpm lint` +- `pnpm test:run` (Vitest) +- `pnpm test:e2e` (Playwright) +- `pnpm test:e2e:install` (Playwright browsers) + +## Supabase (local) +- `supabase start`, `supabase stop`, `supabase status` +- `supabase db reset` is destructive, confirm first. +- Local services: API `http://localhost:54321`, Studio `http://localhost:54323`, Inbucket `http://localhost:54324` (SMTP `54325`). +- Fill `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY` from `supabase status`. + +## Env +- Copy `.env.example` and `supabase/.env.example`. +- Required for auth: `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY`, `SUPABASE_AUTH_GOOGLE_CLIENT_ID`, `SUPABASE_AUTH_GOOGLE_SECRET`. +- Company domain: `NEXT_PUBLIC_COMPANY_EMAIL_DOMAIN`. +- AI (optional): `BEDROCK_AWS_ACCESS_KEY_ID`, `BEDROCK_AWS_SECRET_ACCESS_KEY`, `BEDROCK_MODEL_ID`, optional `BEDROCK_AWS_REGION`. +- Auth/admin: `JWT_SECRET`, `TEST_USER_PASSWORD`. +- Cron/admin: `CRON_SECRET`, `NEXT_PUBLIC_APP_URL`. +- Email: `RESEND_API_KEY`, `EMAIL_FROM`, optional `NEXT_PUBLIC_ENABLE_EMAILS` (local uses Inbucket). +- Optional: `HR_EMAIL`, `LANGSMITH_*`, `ALLOWED_CORS_DOMAIN_SUFFIX`, `CODERPUSH_PULSE_SECRET_KEY`, `NEXT_PUBLIC_GA_ID`. + +## Code Conventions +- TypeScript only. Prefer functional React components and hooks. +- Use `cn` from `src/lib/utils.ts` for class names. +- shadcn/ui style rules in `components.json`. +- Keep new code and tests in `src/`. + +## Key Locations +- `src/app/(authenticated)` user routes: daily-pulse, daily-tasks, submissions, history, leaderboard, profile. +- `src/app/admin` admin UI. +- `src/app/api` API routes: daily tasks, submissions, questions, comments, leaderboard, monthly reports, cron. +- Supabase clients: `src/utils/supabase/{server,client,api,middleware}.ts`. +- Email: `src/lib/email.ts` (Inbucket in dev, Resend in prod). + +## Testing Notes +- E2E tests require local Supabase and the Playwright MCP workflow. See `docs/prompt-work-with-playwright-mcp.md`. +- For Supabase testing strategy, see `docs/supabase-in-test.md` and verify against current code. + +## Docs +- `CLAUDE.md` has extra context; treat `docs/` as design notes and verify against code. diff --git a/README.md b/README.md index 31c1206..d9e7736 100644 --- a/README.md +++ b/README.md @@ -1,215 +1,54 @@ -# Pulse - -[![Next.js](https://img.shields.io/badge/Next.js-15.3.1-black)](https://nextjs.org/) -[![React](https://img.shields.io/badge/React-19.1.0-blue)](https://react.dev/) -[![TypeScript](https://img.shields.io/badge/TypeScript-5.8.3-blue)](https://www.typescriptlang.org/) -[![Supabase](https://img.shields.io/badge/Supabase-Local-orange)](https://supabase.com/) -[![Tailwind CSS](https://img.shields.io/badge/Tailwind-4.1.4-38B2AC)](https://tailwindcss.com/) - -Pulse is a modern, AI-powered web application that revolutionizes team progress tracking and feedback collection through weekly check-ins and daily task management. Built with Next.js 15, React 19, and powered by AWS Bedrock, Pulse provides a seamless experience to maintain consistent communication, track project hours, and gather valuable insights. - -## 🚀 Key Features -### 📅 Daily Tasks Management -- **AI-Powered Task Parsing**: Natural language input that automatically extracts task details -- **Task Extraction**: Parses project names, hours, categories, and descriptions from free text -- **Flexible Input Formats**: Support for manual entry, bulk import, and AI parsing -- **Project & Bucket Categorization**: Organize tasks by project and work type - -### 📊 Weekly Pulse System -- **Multi-Step Submission Forms**: Streamlined weekly check-in process -- **Project Hours Tracking**: Comprehensive time allocation across multiple projects - -### 🎯 Advanced Analytics & Reporting -- **Dashboard Visualizations**: Charts showing effort distribution across projects and categories -- **Time-based Filtering**: Weekly and monthly views with detailed breakdowns -- **Export Capabilities**: PDF and CSV export for reporting and analysis - -## 🏗️ Architecture & Technology Stack - -### Frontend -- **Next.js 15**: App Router with Turbopack for fast development -- **React 19**: Latest React features with concurrent rendering -- **TypeScript**: Full type safety and developer experience -- **Tailwind CSS 4**: Modern utility-first CSS framework -- **shadcn/ui**: Accessible component primitives - -### AI & Backend -- **AWS Bedrock**: Claude and other advanced language models -- **CopilotKit**: AI assistant framework for seamless integration -- **Supabase**: Local PostgreSQL database with real-time capabilities - -### Testing & Quality -- **Vitest**: Fast unit testing framework -- **Playwright**: End-to-end testing with multiple browser support - -## 📁 Project Structure - -``` -pulse/ -├── src/ -│ ├── app/ # Next.js 15 App Router -│ │ ├── (authenticated)/ # Protected routes -│ │ │ ├── daily-tasks/ # Daily task management -│ │ │ ├── submissions/ # Weekly submissions -│ │ │ └── ... # Other authenticated features -│ │ ├── api/ # API routes -│ │ │ ├── copilotkit/ # AI chatbot endpoint -│ │ │ ├── parse-daily-tasks/ # Task parsing API -│ │ │ └── ai-weekly-insight/ # AI insights generation -│ │ └── admin/ # Administrative interfaces -│ ├── components/ # Reusable React components -│ │ ├── CopilotProvider.tsx # AI assistant provider -│ │ ├── DailyPulseAIAssistant.tsx # Daily task AI interface -│ │ └── WeeklyPulseForm.tsx # Weekly form with AI integration -│ ├── lib/ # Utility libraries -│ └── types/ # TypeScript type definitions -├── supabase/ # Database migrations & config -├── e2e/ # End-to-end tests -└── docs/ # Project documentation -``` - -## 🚀 Getting Started - -### Prerequisites -- **Node.js**: 18.x or later -- **PostgreSQL**: 15.x (via Supabase) -- **pnpm**: Package manager -- **Supabase CLI**: For local development - -### Installation - -1. Clone the repository: -```bash -git clone -cd pulse -``` - -2. Install dependencies: -```bash -pnpm install -``` - -3. **Environment Setup** - ```bash - # Copy environment templates - cp .env.example .env - cp supabase/.env.example supabase/.env - - ``` - -4. **Start Local Supabase** - ```bash - supabase start - ``` - -5. **Initialize Database** - ```bash - # ⚠️ WARNING: This resets your local database - supabase db reset - ``` - -6. **Start Development Server** - ```bash - pnpm dev - ``` - -7. **Access the application** - -Frontend: http://localhost:3000 -Admin Dashboard: http://localhost:3000/admin - -## 🤖 AI Features Deep Dive - -### CopilotKit Integration -Pulse uses CopilotKit to provide an intelligent AI assistant that helps users complete forms and manage tasks: - -- **Context Awareness**: The AI remembers user preferences and previous submissions -- **Natural Language Processing**: Users can describe tasks in plain English -- **Smart Form Filling**: AI automatically populates form fields based on conversation -- **Multi-step Guidance**: Breaks down complex forms into manageable conversations - -### Daily Task AI Assistant -The AI-powered daily task system allows users to: - -```typescript -// Example: Natural language task input -"Fixed login bug @project-alpha #bugfix 1.5h -Code review for new feature @project-beta #feature 2 hours" -``` - -**AI automatically extracts:** -- **Date**: Task completion date -- **Project**: Associated project name -- **Category**: Work type (bugfix, feature, etc.) -- **Hours**: Time spent -- **Description**: Task details - -### Weekly Pulse AI Assistant -The weekly form AI assistant provides: - -- **Previous Submission Recall**: Shows last week's data for reference -- **Smart Pre-filling**: Automatically populates form fields -- **Conversational Guidance**: Walks users through form completion -- **Context Preservation**: Maintains conversation state throughout the session - -## 📅 Daily Tasks System - -### Core Features -- **AI-Powered Parsing**: Natural language input processing -- **Calendar View**: Visual submission tracking with color-coded status -- **Dashboard Analytics**: Hours distribution, project breakdowns, and trends -- **Flexible Input Methods**: Multiple ways to add and edit tasks - -### Task Management Workflow -1. **Input**: Users enter tasks via AI assistant or manual forms -2. **Parsing**: AI extracts structured data from natural language -3. **Review**: Tasks are grouped by date with editing capabilities -4. **Submission**: Tasks are saved to the database -5. **Analytics**: Dashboard provides insights and reporting - +# Pulse + +Pulse is an internal web app for weekly pulse submissions, daily task logging, and admin reporting with AI-assisted inputs. It is built with Next.js, Supabase, and CopilotKit. + +## Stack +- Next.js 15 App Router, React 19, TypeScript +- Supabase (Auth + Postgres) +- Tailwind CSS 4 + shadcn/ui +- CopilotKit + AWS Bedrock (AI parsing and insights) + +## Core Areas +- Weekly pulse submissions, history, comments, and sharing +- Daily tasks logging and AI parsing +- Leaderboards and streak tracking +- Admin workflows for submissions, users, projects, time approval, and reminders +- Monthly reports and exports + +## Local Development +1. `pnpm install` +2. `cp .env.example .env` +3. `cp supabase/.env.example supabase/.env` +4. `supabase start` +5. Fill `.env` values from `supabase status` +6. `pnpm dev` + +App: `http://localhost:3000` +Supabase Studio: `http://localhost:54323` +Email (Inbucket): `http://localhost:54324` + +## Scripts +- `pnpm dev` +- `pnpm build` +- `pnpm lint` +- `pnpm test:run` +- `pnpm test:e2e` +- `pnpm test:e2e:install` ## Testing - -This project uses Vitest for unit testing and Playwright for end-to-end (E2E) testing. - -### Unit Tests (Vitest) - -- **Run all unit tests:** - ```bash - pnpm test:run - ``` -- **Run unit tests in watch mode:** - ```bash - pnpm test - ``` -- **Run unit tests with UI:** - ```bash - pnpm test:ui - ``` -- **Generate coverage report:** - ```bash - pnpm test:coverage - ``` - -### End-to-End Tests (Playwright) - -- **Run all E2E tests:** - ```bash - pnpm test:e2e - ``` -- **Run E2E tests with UI mode:** - ```bash - pnpm test:e2e:ui - ``` -- **Run E2E tests in debug mode:** - ```bash - pnpm test:e2e:debug - ``` -- **Run E2E tests specifically for Chromium:** - ```bash - pnpm test:e2e:chromium - ``` -- **Generate code for E2E tests:** - ```bash - pnpm test:e2e:codegen - ``` \ No newline at end of file +- Unit: `pnpm test:run` +- E2E: `pnpm test:e2e` (requires local Supabase and Playwright MCP) +- Debug/UI: `pnpm test:e2e:debug`, `pnpm test:e2e:ui` + +## Env Notes +- AI endpoints require `BEDROCK_AWS_ACCESS_KEY_ID`, `BEDROCK_AWS_SECRET_ACCESS_KEY`, `BEDROCK_MODEL_ID` (optional `BEDROCK_AWS_REGION`). +- Cron endpoints require `CRON_SECRET`. +- Email uses Resend in production; locally it uses Supabase Inbucket. Set `NEXT_PUBLIC_ENABLE_EMAILS=true` to send share emails. +- Auth uses `NEXT_PUBLIC_COMPANY_EMAIL_DOMAIN`; auto-login uses `JWT_SECRET` + `TEST_USER_PASSWORD`. Optional `HR_EMAIL` controls monthly report recipients. + +## Project Structure +- `src/app` routes (authenticated user flows, admin UI, API routes) +- `src/components` UI +- `src/utils/supabase` Supabase clients +- `supabase/` migrations, config, seed data +- `docs/` design notes and plans diff --git a/docs/implementation.md b/docs/implementation.md index bcd9367..5de10f9 100644 --- a/docs/implementation.md +++ b/docs/implementation.md @@ -1,233 +1,47 @@ -# Weekly Pulse Implementation Guide - -## Tech Stack Overview - -- **Frontend**: Next.js 14 with App Router, React 18, Tailwind CSS 3 -- **UI Components**: shadcn/ui -- **Backend**: Supabase (Auth + Database) -- **Database**: PostgreSQL with Drizzle ORM -- **Email**: Resend for production, Mailtrap for staging -- **Deployment**: Vercel -- **Background Jobs**: Vercel Cron Jobs - -## Project Structure - -``` -src/ -├── app/ # Next.js app router pages -│ ├── admin/ # Admin dashboard routes -│ ├── api/ # API routes -│ ├── auth/ # Authentication routes -│ ├── history/ # User history view -│ └── page.tsx # Main submission form -├── components/ # Reusable UI components -│ ├── ui/ # shadcn components -│ ├── screens/ # Form screens -│ └── admin/ # Admin components -├── constants/ # App-wide constants -├── db/ # Database schema and queries -├── lib/ # Utility functions -├── types/ # TypeScript type definitions -└── utils/ # Helper functions -``` - -## UI Component Strategy - -### Implemented shadcn Components -- Button -- Input -- Textarea -- Progress -- Card -- Form -- Toast -- Dialog - -### Components To Be Added -- Command (for project search) -- DataTable (for admin views) -- Calendar (for week selection) -- Tabs (for admin dashboard) - -### Form Implementation -```tsx -// Example form screen component -import { Button } from "@/components/ui/button" -import { Card } from "@/components/ui/card" -import { Input } from "@/components/ui/input" - -export function ProjectSelectionScreen() { - return ( - - setProject(e.target.value)} - /> - - - ) -} -``` - -## Data Model - -### Current Tables -1. **users** - - id (UUID, primary key) - - email (string, unique) - - name (string) - - created_at (timestamp) - - is_admin (boolean) - -2. **submissions** - - id (UUID, primary key) - - user_id (UUID, foreign key) - - week_number (integer) - - project (string) - - hours_worked (integer) - - manager_email (string) - - notes (text, nullable) - - submitted_at (timestamp) - - is_late (boolean) - -### Planned Tables -1. **projects** - - id (UUID, primary key) - - name (string, unique) - - created_at (timestamp) - -2. **reminder_logs** - - id (UUID, primary key) - - user_id (UUID, foreign key) - - week_number (integer) - - sent_at (timestamp) - - type (enum: first, second, final) - -## Key Components - -### Authentication (Implemented) -- Supabase Auth with Google and Magic Link -- Protected routes via middleware -- Admin role management - -### Submission Flow (Implemented) -1. Welcome Screen -2. Project Selection -3. Hours Worked -4. Manager Selection -5. Feedback -6. Review & Submit - -### Admin Dashboard (In Progress) -- Submission tracking -- User management -- Data export -- Analytics dashboard - -### History View (Planned) -- Personal submission history -- Week navigation -- Export functionality - -## API Routes - -1. `/api/submissions` - - POST: Create submission - - GET: List submissions (with filters) - -2. `/api/weeks` - - GET: Get current week - - GET: List available weeks - -Planned Routes: -1. `/api/projects` - - GET: List projects - - POST: Create project - -2. `/api/admin` - - GET: Dashboard stats - - GET: User management - - POST: Import data - -## Background Jobs (Planned) - -### Reminder System -1. **Friday 5PM**: Form opens for next week -2. **Monday 2PM**: On-time deadline -3. **Monday 5PM**: First reminder -4. **Tuesday 9AM**: Second reminder -5. **Tuesday 5PM**: Final cutoff - -### Data Management -- Weekly submission window generation -- Data cleanup and archival -- Analytics generation - -## Environment Variables - -```env -# Required -NEXT_PUBLIC_SUPABASE_URL=your_supabase_url -NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key -SUPABASE_SERVICE_ROLE_KEY=your_service_role_key - -# Optional -RESEND_API_KEY=your_resend_key -MAILTRAP_API_KEY=your_mailtrap_key -``` - -## Implementation Guidelines - -1. **Mobile First** - - All components are responsive - - Touch-friendly inputs - - Minimal scrolling - -2. **Performance** - - Client-side caching - - Optimistic updates - - Lazy loading for history - -3. **Error Handling** - - Form validation - - Network error recovery - - Toast notifications - -4. **Accessibility** - - ARIA labels - - Keyboard navigation - - Color contrast compliance - -## Testing Strategy - -1. **Unit Tests** (To Be Implemented) - - Form validation - - Date calculations - - Utility functions - -2. **Integration Tests** (To Be Implemented) - - Submission flow - - Authentication - - Admin features - -3. **E2E Tests** (To Be Implemented) - - Complete user journey - - Admin workflows - -## Deployment Checklist - -1. **Pre-launch** - - Database migrations - - Environment setup - - Email configuration - - Admin user creation - -2. **Launch** - - Deploy to staging - - QA testing - - Deploy to production - -3. **Post-launch** - - Monitor errors - - Track performance - - Gather feedback \ No newline at end of file +# Pulse Implementation Guide + +## Stack (Current) +- Next.js 15 App Router, React 19, TypeScript +- Tailwind CSS 4 + shadcn/ui +- Supabase (Auth + Postgres) +- CopilotKit + AWS Bedrock for AI features +- Email: Resend in production, Inbucket locally +- Testing: Vitest + Playwright + +## App Structure +- `src/app/(authenticated)` user flows: daily-pulse, daily-tasks, submissions, history, leaderboard, profile +- `src/app/admin` admin UI: submissions, users, projects, time approval, follow-ups, questions, daily tasks +- `src/app/api` API routes: submissions, questions, comments, daily tasks, leaderboard, monthly reports, cron +- `src/utils/supabase` Supabase clients for server/client/middleware +- `src/lib` shared helpers (email, prompts, utils) + +## Auth +- Supabase SSR clients in `src/utils/supabase`. +- Google OAuth configured via Supabase; domain restriction uses `NEXT_PUBLIC_COMPANY_EMAIL_DOMAIN`. +- Auto-login endpoint uses `JWT_SECRET` + `TEST_USER_PASSWORD`. + +## Data Model (High Level) +- Core: `users`, `weeks`, `submissions`, `submission_answers`, `submission_shares`, `questions`, `comments` +- Reporting: `templates`, `template_questions`, `submission_periods`, `submission_period_users`, `recurring_schedules` +- Tasks/projects: `daily_tasks`, `projects` +- Monthly: `monthly_reports`, `monthly_report_comments` +- Utility: `reminder_logs` +- Canonical schema is in `supabase/migrations/`. + +## AI +- `/api/copilotkit` runtime for the UI assistant +- `/api/parse-daily-tasks` and `/api/ai-weekly-insight` use Bedrock models + +## Email +- `src/lib/email.ts` routes to Inbucket when `NODE_ENV=development` and Resend otherwise. +- Sharing emails are gated by `NEXT_PUBLIC_ENABLE_EMAILS=true`. + +## Cron +- Cron endpoints live under `/api/cron/*` and call admin reminder routes. +- `CRON_SECRET` is required for cron/authenticated reminder endpoints. +- Vercel cron schedules are defined in `vercel.json`. + +## More Detail +- Testing: `docs/test-plan.md` +- Supabase testing strategy: `docs/supabase-in-test.md` +- Playwright MCP requirement: `docs/prompt-work-with-playwright-mcp.md` diff --git a/docs/supabase-in-test.md b/docs/supabase-in-test.md index 3c6e876..a064132 100644 --- a/docs/supabase-in-test.md +++ b/docs/supabase-in-test.md @@ -1,268 +1,25 @@ -# Supabase Testing Strategy +# Supabase in Tests -## Overview -This document outlines our approach to testing Supabase functionality in the Pulse application. We use a hybrid approach combining mocked Supabase for unit tests and real Supabase local for integration tests. +## Default Approach +- Unit/integration tests use mocks. +- E2E tests use local Supabase. -## Testing Approaches Comparison - -### Using Real Supabase Local - -#### Advantages -1. **Realistic Testing** - - Tests run against actual database schema - - Real SQL queries and responses - - Catches database constraints and type issues - - Tests Row Level Security (RLS) policies - - Validates migrations and schema changes - -2. **Easier Setup** - - Leverages existing Supabase local setup - - No need to maintain mock implementations - - No risk of mocks becoming outdated - - Real-world behavior in tests - -3. **Better Integration Coverage** - - Tests actual data flows - - Validates SQL query performance - - Catches real-world edge cases - - Tests database triggers and functions - -#### Disadvantages -1. **Test Performance** - - Slower test execution due to real DB operations - - Network latency (even if local) - - Each test needs database cleanup - - Longer CI/CD pipeline times - -2. **Test Isolation Challenges** - - Need to manage test data cleanup - - Potential for test interference - - Complex state management between tests - - Transaction management overhead - -3. **CI/CD Complexity** - - Requires Supabase setup in CI environment - - Potential for flaky tests due to timing - - Additional infrastructure requirements - -### Using Mocked Supabase - -#### Advantages -1. **Performance** - - Fast test execution (in-memory) - - No network latency - - No actual DB operations - - Quick feedback loop during development - -2. **Perfect Isolation** - - Tests run independently - - No state cleanup needed - - Predictable test behavior - - Easy to test edge cases - -3. **Development Experience** - - Can run tests without Supabase - - No external service dependencies - - Works offline - - Faster test writing - -#### Disadvantages -1. **Maintenance Overhead** - - Must maintain mock implementations - - Mocks can become outdated - - Need to sync with schema changes - - Complex query mocking - -2. **Less Realistic** - - May miss real database issues - - Cannot test RLS policies - - SQL query issues might be missed - - No real performance testing - -3. **Reliability Concerns** - - Tests might pass but fail in production - - Mock behavior might differ from real DB - - False sense of security - - Missing edge cases - -## Our Hybrid Approach - -We use a hybrid approach that leverages the strengths of both methods: - -### 1. Unit Tests (Mocked Supabase) -Use mocked Supabase for: -- Component testing -- UI interaction testing -- Error handling -- Loading states - -Example mock setup: -```typescript -// src/__tests__/__mocks__/supabase.ts -import { vi } from 'vitest' - -export const mockSupabaseClient = { - auth: { - signInWithOAuth: vi.fn(), - getSession: vi.fn(), - signOut: vi.fn(), - onAuthStateChange: vi.fn() - }, - from: (table: string) => ({ - select: vi.fn().mockReturnThis(), - insert: vi.fn().mockReturnThis(), - update: vi.fn().mockReturnThis(), - delete: vi.fn().mockReturnThis(), - eq: vi.fn().mockReturnThis(), - single: vi.fn() - }) -} -``` - -Example component test: -```typescript -import { render, screen } from '@testing-library/react' +## Mocks +- Helper: `src/test-utils/supabase-mocks.ts` +- Example usage: +```ts +import { setupSupabaseMocks } from '@/test-utils/supabase-mocks' import { vi } from 'vitest' -import { mockSupabaseClient } from '../__mocks__/supabase' -import SubmissionForm from './SubmissionForm' -vi.mock('@/lib/supabase', () => ({ - createClient: () => mockSupabaseClient -})) - -describe('SubmissionForm', () => { - it('handles successful submission', async () => { - mockSupabaseClient.from('submissions') - .insert - .mockResolvedValueOnce({ data: { id: 1 }, error: null }) - - render() - // Test form submission... - }) -}) -``` - -### 2. Integration Tests (Real Supabase Local) -Use real Supabase local for: -- Critical user flows -- Data persistence -- RLS policy validation -- Complex queries - -Example integration test: -```typescript -import { createClient } from '@/lib/supabase' -import { beforeEach, describe, it, expect } from 'vitest' - -const supabase = createClient() - -describe('Weekly submission flow', () => { - beforeEach(async () => { - // Clean up test data - await supabase.from('submissions').delete().neq('id', 0) - await supabase.from('users').delete().neq('id', 0) - }) - - it('creates a new submission', async () => { - const { data, error } = await supabase - .from('submissions') - .insert({ - week_number: 1, - hours: 40, - notes: 'Test submission' - }) - .select() - - expect(error).toBeNull() - expect(data?.[0]).toMatchObject({ - week_number: 1, - hours: 40, - notes: 'Test submission' - }) - }) -}) -``` - -## Best Practices - -### 1. Test Data Management -- Use unique identifiers for test data -- Clean up data before/after tests -- Use transactions where possible -- Avoid test data collision - -### 2. Mocking Guidelines -- Mock at the lowest possible level -- Keep mocks simple and focused -- Update mocks when schema changes -- Document mock behavior - -### 3. Test Organization -- Separate unit and integration tests -- Group tests by feature/flow -- Clear naming conventions -- Consistent test structure - -### 4. CI/CD Considerations -- Set up Supabase local in CI -- Use test database -- Parallel test execution -- Proper error handling - -## Implementation Example - -### Directory Structure -```plaintext -src/ -├── __tests__/ -│ ├── __mocks__/ -│ │ └── supabase.ts # Supabase mocks -│ ├── unit/ -│ │ └── components/ # Component tests with mocks -│ └── integration/ -│ └── flows/ # Integration tests with real DB +vi.mock('@/utils/supabase/server') +const { mockSupabaseClient } = setupSupabaseMocks() ``` -### Test Configuration -```typescript -// vitest.config.ts -export default defineConfig({ - test: { - environment: 'jsdom', - setupFiles: ['./src/test/setup.ts'], - globalSetup: './src/test/global-setup.ts', // Supabase setup - } -}) -``` - -## When to Use What - -### Use Mocks For: -- UI component tests -- Error state testing -- Loading state testing -- Event handler testing -- Form validation -- Navigation testing - -### Use Real Supabase For: -- Data persistence flows -- Authentication flows -- RLS policy validation -- Complex queries -- Database triggers -- Real-world scenarios - -## Conclusion -This hybrid approach gives us: -- Fast and reliable unit tests -- Comprehensive integration testing -- Confidence in database operations -- Maintainable test suite -- Good developer experience +## When to Use Local Supabase +- E2E flows +- RLS policy checks +- Real SQL behaviors (constraints, RPCs, triggers) -Remember to: -- Keep mocks up-to-date -- Clean up test data -- Document test patterns -- Review test coverage regularly \ No newline at end of file +## Notes +- Local Supabase must be running for E2E. +- See `docs/prompt-work-with-playwright-mcp.md` for MCP requirements. diff --git a/docs/test-plan.md b/docs/test-plan.md index 5c8b904..d595cc6 100644 --- a/docs/test-plan.md +++ b/docs/test-plan.md @@ -1,287 +1,32 @@ -# Test Plan for Pulse - -## Overview -This document outlines the testing strategy for the Pulse application, using Vitest for unit/integration tests and Playwright for end-to-end (E2E) testing. - -## Test Stack - -### Unit and Integration Tests (Vitest) -- **Framework**: Vitest + React Testing Library -- **Key Dependencies**: - ```json - { - "@testing-library/react": "^14.2.1", - "@testing-library/user-event": "^14.5.2", - "@vitejs/plugin-react": "^4.2.1", - "vitest": "^1.3.1", - "jsdom": "^24.0.0", - "@vitest/coverage-v8": "^1.3.1" - } - ``` - -### End-to-End Tests (Playwright) -- **Framework**: Playwright Test -- **Key Dependencies**: - ```json - { - "@playwright/test": "^1.42.1", - "@types/node": "^20.11.24" - } - ``` - -## Directory Structure - -``` -├── src/ -│ ├── components/ -│ │ ├── ui/ -│ │ │ ├── button/ -│ │ │ │ ├── Button.tsx -│ │ │ │ └── Button.test.tsx <-- Test colocated with component -│ │ ├── WeekFilter/ -│ │ │ ├── WeekFilter.tsx -│ │ │ └── WeekFilter.test.tsx <-- Test colocated with component -│ ├── lib/ -│ │ ├── utils/ -│ │ │ ├── time.ts -│ │ │ ├── time.test.ts <-- Test colocated with utility -│ │ │ ├── date.ts -│ │ │ └── date.test.ts <-- Test colocated with utility -│ ├── app/ -│ │ ├── (authenticated)/ -│ │ │ ├── history/ -│ │ │ │ ├── page.tsx -│ │ │ │ └── page.test.tsx <-- Test colocated (if needed for client logic) -│ ├── hooks/ -│ │ ├── useMyHook.ts -│ │ └── useMyHook.test.ts <-- Test colocated with hook -│ ├── test/ # Optional: For global setup/mocks -│ │ ├── setup.ts -│ │ └── __mocks__/ -│ └── ... (other source files and their tests) -├── e2e/ # Playwright tests -│ ├── auth.setup.ts # Auth setup for E2E -│ ├── fixtures/ # Test fixtures -│ └── specs/ # Test specifications -├── vitest.config.ts # Vitest configuration -└── playwright.config.ts # Playwright configuration -``` - -## Test Categories - -### 1. Unit Tests (Vitest) -- **Location**: Colocated with source files (e.g., `Button.test.tsx` next to `Button.tsx`). Tests focus on individual components or functions in isolation, mocking dependencies. -- **Coverage Areas**: - - React Components (Rendering, Props, Basic Interaction) - - Utility Functions - - Hooks - - State Management - - Helper Functions - -### 2. Integration Tests (Vitest) -- **Location**: Colocated with the primary source file orchestrating the interaction (e.g., a page component's test file `page.test.tsx`). Tests focus on how multiple units work together, potentially with mocked external services (like Supabase). -- **Coverage Areas**: - - Component Interactions within a feature or page - - API Route Handlers - - Data Flow - - State Management Integration - - Supabase Client Integration - -### 3. E2E Tests (Playwright) -- **Location**: `e2e/specs/` -- **Coverage Areas**: - - User Flows - - Authentication (Google OAuth) - - Form Submissions - - Navigation - - Data Persistence - -## Configuration Files - -### Vitest Configuration -Will be added to `vitest.config.ts`: -```typescript -import { defineConfig } from 'vitest/config' -import react from '@vitejs/plugin-react' -import { resolve } from 'path' - -export default defineConfig({ - plugins: [react()], - test: { - environment: 'jsdom', - include: ['src/**/*.{test,spec}.{js,jsx,ts,tsx}'], - globals: true, - setupFiles: ['./src/test/setup.ts'], - coverage: { - provider: 'v8', - reporter: ['text', 'json', 'html'], - exclude: [ - 'node_modules/', - 'src/test/setup.ts', - ], - }, - }, - resolve: { - alias: { - '@': resolve(__dirname, './src'), - }, - }, -}) -``` - -### Playwright Configuration -Will be added to `playwright.config.ts`: -```typescript -import { defineConfig, devices } from '@playwright/test' - -export default defineConfig({ - testDir: './e2e', - fullyParallel: true, - forbidOnly: !!process.env.CI, - retries: process.env.CI ? 2 : 0, - workers: process.env.CI ? 1 : undefined, - reporter: 'html', - use: { - baseURL: 'http://localhost:3000', - trace: 'on-first-retry', - storageState: './e2e/fixtures/storageState.json', - }, - projects: [ - { - name: 'setup', - testMatch: /auth\.setup\.ts/, - }, - { - name: 'chromium', - use: { ...devices['Desktop Chrome'] }, - dependencies: ['setup'], - }, - { - name: 'firefox', - use: { ...devices['Desktop Firefox'] }, - dependencies: ['setup'], - }, - { - name: 'webkit', - use: { ...devices['Desktop Safari'] }, - dependencies: ['setup'], - }, - ], -}) -``` - -## Test Scripts -Will be added to `package.json`: -```json -{ - "scripts": { - "test": "vitest", - "test:ui": "vitest --ui", - "test:run": "vitest run", - "test:coverage": "vitest run --coverage", - "test:e2e": "playwright test", - "test:e2e:ui": "playwright test --ui", - "test:e2e:debug": "playwright test --debug" - } -} -``` - -## Authentication Testing Strategy - -### Unit/Integration Tests -- Mock Supabase authentication -- Test auth state management -- Test protected routes -- Test auth-related components - -### E2E Tests -- Use Playwright's built-in authentication handling -- Store authenticated state for reuse -- Test real Google OAuth flow -- Verify protected routes with authenticated sessions - -## CI/CD Integration - -### GitHub Actions Configuration -Will be added to `.github/workflows/test.yml`: -```yaml -name: Tests -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v2 - - uses: actions/setup-node@v4 - with: - node-version: '20' - cache: 'pnpm' - - name: Install dependencies - run: pnpm install - - name: Run unit & integration tests - run: pnpm test:run - - name: Install Playwright browsers - run: pnpm playwright install --with-deps - - name: Run E2E tests - run: pnpm test:e2e -``` - -## Implementation Plan - -1. **Phase 1: Setup (Week 1)** - - Install test dependencies - - Configure Jest and Playwright - - Set up CI pipeline - - Create initial test structure - -2. **Phase 2: Unit Tests (Week 2)** - - Implement component tests - - Add utility function tests - - Set up mock services - -3. **Phase 3: Integration Tests (Week 3)** - - Add API route tests - - Implement Supabase integration tests - - Test component interactions - -4. **Phase 4: E2E Tests (Week 4)** - - Set up auth flows - - Implement critical user journeys - - Add cross-browser testing - -## Code Coverage Goals - -- Unit Tests: 80% coverage -- Integration Tests: 70% coverage -- E2E Tests: Cover all critical user paths - -## Best Practices - -1. **Test Organization** - - One test file per component/feature - - Clear test descriptions - - Consistent naming conventions - -2. **Testing Principles** - - Test behavior, not implementation - - Keep tests independent - - Use meaningful assertions - - Follow AAA pattern (Arrange, Act, Assert) - -3. **Mocking Strategy** - - Mock external services - - Use fixtures for test data - - Maintain mock data separately - -## Review and Maintenance - -- Regular review of test coverage -- Update tests with new features -- Maintain test documentation -- Regular cleanup of obsolete tests \ No newline at end of file +# Test Plan + +## Stack +- Unit/Integration: Vitest + React Testing Library (jsdom) +- E2E: Playwright + +## Locations +- Unit/integration tests: `src/**/*.{test,spec}.{ts,tsx}` +- Test setup: `src/test/setup.ts` +- Supabase mocks: `src/test-utils/supabase-mocks.ts` +- E2E tests: `e2e/specs/*.spec.ts` + +## Configuration +- `vitest.config.ts`: jsdom, setup file, `@` alias +- `playwright.config.ts`: `pnpm dev` webServer, base URL `http://localhost:3000`, Chromium/Firefox/WebKit + +## Commands +- `pnpm test` (watch) +- `pnpm test:run` +- `pnpm test:ui` +- `pnpm test:coverage` +- `pnpm test:e2e` +- `pnpm test:e2e:debug` +- `pnpm test:e2e:ui` +- `pnpm test:e2e:install` + +## Supabase Strategy +- Prefer mocks for unit/integration tests. +- Use local Supabase for E2E and any flow tests that require real DB/RLS. + +## MCP Requirement +E2E runs must use Playwright MCP. See `docs/prompt-work-with-playwright-mcp.md`. diff --git a/package.json b/package.json index 39fb811..b509e5a 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ }, "devDependencies": { "@eslint/eslintrc": "^3.3.1", + "@next/eslint-plugin-next": "15.3.1", "@playwright/test": "^1.52.0", "@tailwindcss/postcss": "^4.1.4", "@testing-library/jest-dom": "^6.6.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2343cc2..39d3517 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -165,6 +165,9 @@ importers: '@eslint/eslintrc': specifier: ^3.3.1 version: 3.3.1 + '@next/eslint-plugin-next': + specifier: 15.3.1 + version: 15.3.1 '@playwright/test': specifier: ^1.52.0 version: 1.52.0