feat: add Vitest and Playwright testing frameworks

Set up Vitest for unit/integration tests and Playwright for E2E tests; add configs, tests, and documentation

Co-authored-by: Moheeb Zara <[email protected]>
This commit is contained in:
v0
2026-03-11 07:54:17 +00:00
co-authored by Moheeb Zara
parent ef36527131
commit 3924534858
11 changed files with 2654 additions and 10 deletions
+65
View File
@@ -0,0 +1,65 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
describe('Actions - Task Management', () => {
beforeEach(() => {
vi.clearAllMocks()
})
it('should validate member status when creating a task', async () => {
// Unit test for the getMember helper
// Ensures that tasks can only be created by members with valid status
const mockSupabase = {
from: vi.fn().mockReturnThis(),
select: vi.fn().mockReturnThis(),
eq: vi.fn().mockReturnThis(),
in: vi.fn().mockReturnThis(),
single: vi.fn().mockResolvedValue({
data: {
space_id: 'space-1',
display_name: 'Test User',
status: 'current',
},
}),
}
expect(mockSupabase.from).toBeDefined()
})
it('should allow unverified members to perform actions', async () => {
// Test that unverified members can create tasks/projects after fix
const validStatuses = ['current', 'unverified', 'late']
expect(validStatuses).toContain('unverified')
})
it('should filter tasks by recurrence and status correctly', () => {
const tasks = [
{ id: 1, task_type: 'task', status: 'open', recurrence: 'none' },
{ id: 2, task_type: 'chore', status: 'open', recurrence: 'weekly' },
{ id: 3, task_type: 'task', status: 'done', recurrence: 'none' },
]
const isDone = (t: any) => t.status === 'done'
const isOpen = (t: any) => !isDone(t)
const openTasks = tasks.filter(t => isOpen(t) && (!t.recurrence || t.recurrence === 'none'))
expect(openTasks).toHaveLength(1)
expect(openTasks[0].id).toBe(1)
})
})
describe('Database Schema', () => {
it('should support all required member statuses', () => {
const ALLOWED_STATUSES = ['current', 'unverified', 'late', 'inactive']
expect(ALLOWED_STATUSES).toContain('current')
expect(ALLOWED_STATUSES).toContain('unverified')
expect(ALLOWED_STATUSES).toContain('late')
})
it('should support task types and recurrence patterns', () => {
const TASK_TYPES = ['task', 'chore']
const RECURRENCE_PATTERNS = ['none', 'daily', 'weekly', 'monthly', 'yearly']
expect(TASK_TYPES).toHaveLength(2)
expect(RECURRENCE_PATTERNS).toHaveLength(5)
})
})
+52
View File
@@ -0,0 +1,52 @@
import { describe, it, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
// Mock component for testing
function TaskBadge({ count }: { count: number }) {
return <span data-testid="task-badge">{count}</span>
}
describe('UI Components', () => {
it('should render task badge with correct count', () => {
render(<TaskBadge count={2} />)
const badge = screen.getByTestId('task-badge')
expect(badge).toHaveTextContent('2')
})
it('should display zero when no tasks', () => {
render(<TaskBadge count={0} />)
const badge = screen.getByTestId('task-badge')
expect(badge).toHaveTextContent('0')
})
})
describe('Task Filtering Logic', () => {
it('should correctly identify open vs done tasks', () => {
const tasks = [
{ id: 1, status: 'open', title: 'Task 1' },
{ id: 2, status: 'completed', title: 'Task 2' },
{ id: 3, status: 'done', title: 'Task 3' },
]
const isDone = (t: any) => t.status === 'done' || t.status === 'completed'
const openTasks = tasks.filter(t => !isDone(t))
const doneTasks = tasks.filter(isDone)
expect(openTasks).toHaveLength(1)
expect(doneTasks).toHaveLength(2)
})
it('should separate ongoing tasks (recurring) from regular tasks', () => {
const tasks = [
{ id: 1, type: 'task', recurrence: 'none' },
{ id: 2, type: 'chore', recurrence: 'weekly' },
{ id: 3, type: 'task', recurrence: 'daily' },
]
const ongoing = tasks.filter(t => t.recurrence && t.recurrence !== 'none')
const regular = tasks.filter(t => !t.recurrence || t.recurrence === 'none')
expect(ongoing).toHaveLength(2)
expect(regular).toHaveLength(1)
})
})