Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
node_modules/
backend/venv/
backend/__pycache__/
backend/*.db
backend/*.csv
cucumber-report/
playwright-report/
test-results/
frontend/dist/
frontend/node_modules/
*.pyc
30 changes: 30 additions & 0 deletions SPECS/add-expense.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Feature Spec: Add Expense

## Goal
- Allow a user to log a new expense with amount, category, description, and date.

## Scope
- In: Amount (required), category (required), description (optional), date (defaults to today)
- Out: Recurring expenses, attachments, currency conversion

## Categories
`food` | `transport` | `entertainment` | `shopping` | `health` | `bills` | `other`

## Requirements
- `POST /expenses` accepts `{ amount, category, description, date }`
- Amount must be a positive number (max 2 decimal places)
- Category must be one of the valid enum values
- Description is optional (max 500 chars)
- Date defaults to today if not provided
- Frontend shows a form with all fields
- On success, the new expense appears in the list immediately

## Acceptance Criteria
- [x] User can fill in the form and submit a new expense
- [x] Expense appears in the list after creation
- [x] Empty or zero amount shows a validation error
- [x] Invalid category returns 422 from API
- [x] Date defaults to today when not provided
- [x] Expense is persisted across page reloads
- [x] Amount accepts at most 2 decimal places

29 changes: 29 additions & 0 deletions SPECS/architecture-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Feature Spec: Architecture Overview

## Goal
- Define the overall architecture for the Expense Tracker application.

## Scope
- In: Frontend (React + TypeScript + Vite), Backend (Python + FastAPI + SQLite), E2E Tests (Playwright + TypeScript)
- Out: Authentication, multi-user support, cloud deployment

## Requirements
- Backend exposes a REST API on port 8000
- Frontend runs on port 5173 (Vite default)
- Data is persisted in a local SQLite database (`expenses.db`)
- Playwright tests run against the live frontend + backend

## Stack
| Layer | Technology |
|----------|-------------------------------|
| Frontend | React + TypeScript + Vite |
| Backend | Python + FastAPI + SQLAlchemy |
| Database | SQLite (`expenses.db`) |
| Tests | Playwright + TypeScript |

## Acceptance Criteria
- [ ] Frontend communicates with backend via REST API
- [ ] Backend persists data in SQLite
- [ ] All services run locally with simple commands
- [ ] Playwright tests can run against local stack

28 changes: 28 additions & 0 deletions SPECS/cucumber-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Feature Spec: Cucumber HTML Report

## Goal
- Generate a human-readable Cucumber HTML report from Playwright test results.

## Scope
- In: Cucumber JSON output, HTML report generation, browser metadata
- Out: CI/CD integration, Slack notifications, email reports

## Requirements
- Custom Playwright reporter converts test results to Cucumber JSON format
- JSON output saved to `cucumber-report/results.json`
- HTML report generated from JSON using `multiple-cucumber-html-reporter`
- HTML report saved to `cucumber-report/html/index.html`
- Report includes browser name, version, and platform metadata
- `npm run test:cucumber` runs tests and generates the report in one command
- `npm run cucumber:report` regenerates the HTML from existing JSON without re-running tests
- `npm run clean` deletes all report directories

## Acceptance Criteria
- [x] Playwright test results are converted to Cucumber JSON format
- [x] Cucumber HTML report is generated after test run
- [x] Report displays browser name and version (Chrome + version number)
- [x] Report groups tests into feature suites matching spec files
- [x] All test scenarios show pass/fail status
- [x] `npm run test:cucumber` runs tests and generates report in one step
- [x] `npm run clean` removes all generated report directories

26 changes: 26 additions & 0 deletions SPECS/edit-delete-expense.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Feature Spec: Edit and Delete Expense

## Goal
- Allow a user to edit or permanently delete an existing expense.

## Scope
- In: Edit amount, category, description, date. Delete by ID.
- Out: Soft delete, undo, audit history

## Requirements
- `PATCH /expenses/{id}` accepts partial updates: `{ amount?, category?, description?, date? }`
- `DELETE /expenses/{id}` removes the expense permanently
- Both return 404 if expense not found
- DELETE returns 204 No Content on success
- Frontend shows an edit button that opens a pre-filled form
- Frontend shows a delete button with a confirmation step

## Acceptance Criteria
- [x] User can edit any field of an existing expense
- [x] Edited expense reflects changes immediately in the list
- [x] User can delete an expense
- [x] Deleted expense no longer appears after refresh
- [x] Editing a non-existent expense returns 404
- [x] Deleting a non-existent expense returns 404
- [x] Invalid amount or category on edit returns 422

25 changes: 25 additions & 0 deletions SPECS/filter-search-expenses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Feature Spec: Filter and Search Expenses

## Goal
- Allow a user to filter expenses by category and search by description keyword.

## Scope
- In: Filter by category, search by keyword in description
- Out: Date range filter, multi-category filter

## Requirements
- `GET /expenses?category=food` filters by category
- `GET /expenses?search=keyword` searches description (case-insensitive)
- Filters can be combined: `GET /expenses?category=food&search=lunch`
- Frontend shows category filter tabs: All | Food | Transport | Entertainment | Shopping | Health | Bills | Other
- Frontend shows a search input field with debounced updates

## Acceptance Criteria
- [x] Clicking a category tab shows only expenses in that category
- [x] Clicking "All" restores full list
- [x] Search returns expenses whose description contains the keyword
- [x] Search is case-insensitive
- [x] Search and category filter work together
- [x] No results shows empty state message
- [x] Clearing search restores the filtered or full list

70 changes: 70 additions & 0 deletions SPECS/playwright-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Feature Spec: Playwright E2E Tests

## Goal
- Validate all key workflows end-to-end using Playwright + TypeScript.

## Scope
- In: Full E2E tests for CRUD, filter, search, and summary workflows
- Out: Unit tests, API-only tests

## Requirements
- Playwright configured with TypeScript
- Tests run against local frontend (port 5173) + backend (port 8000)
- Each test is isolated (cleans up created expenses)
- Tests cover happy paths and key edge cases

## Test Cases

### Add Expense
- [x] Can add an expense with amount, category, and description
- [x] Can add an expense without description
- [x] Shows validation error for missing amount
- [x] Shows validation error for zero or negative amount
- [x] Date defaults to today when not provided
- [x] Expense persists across page reload

### View Expenses
- [x] Expenses appear in the list on page load
- [x] Empty state is shown when no expenses exist
- [x] Expenses are sorted by date descending
- [x] Each expense shows the date field in the list

### Edit Expense
- [x] Can edit the amount of an existing expense
- [x] Can change the category of an expense
- [x] Edited values reflect immediately in the list
- [x] Can cancel editing without saving changes

### Delete Expense
- [x] Can delete an expense
- [x] Deleted expense no longer appears in the list

### API Error Handling
- [x] Editing a non-existent expense returns 404
- [x] Deleting a non-existent expense returns 404
- [x] Invalid amount on edit returns 422

### Filter by Category
- [x] Clicking a category tab shows only that category's expenses
- [x] Clicking "All" restores the full list
- [x] Switching between categories updates the list

### Search
- [x] Search returns matching expenses by description
- [x] Search is case-insensitive
- [x] No results shows empty state
- [x] Clearing search restores the list
- [x] Search and category filter work together

### Summary Stats
- [x] Grand total updates when an expense is added
- [x] Category total updates when an expense is added
- [x] Totals update when an expense is deleted
- [x] Totals update when an expense is edited
- [x] Category row disappears when all expenses in that category are deleted
- [x] Summary shows totals per category for multiple expenses

## Acceptance Criteria
- [x] All tests pass with `npx playwright test`
- [x] HTML test report is generated
- [x] Tests are isolated and do not depend on each other
24 changes: 24 additions & 0 deletions SPECS/summary-stats.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Feature Spec: Summary Statistics

## Goal
- Display a summary of total spending per category and an overall grand total.

## Scope
- In: Total per category, grand total across all expenses
- Out: Charts/graphs, monthly breakdowns, budget limits

## Requirements
- `GET /expenses/summary` returns totals per category and grand total
- Response shape: `{ total: number, by_category: { [category]: number } }`
- Frontend displays a summary panel/card above the expense list
- Totals update in real-time when expenses are added, edited, or deleted

## Acceptance Criteria
- [x] Summary panel shows grand total of all expenses
- [x] Summary panel shows total per category
- [x] Totals update immediately when an expense is added
- [x] Totals update immediately when an expense is edited
- [x] Totals update immediately when an expense is deleted
- [x] Zero-spend categories are not shown in the summary
- [x] API returns correct totals matching the stored expenses

23 changes: 23 additions & 0 deletions SPECS/view-expenses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Feature Spec: View Expenses

## Goal
- Display all expenses in a list, sorted by date descending.

## Scope
- In: List of all expenses with amount, category, description, date
- Out: Pagination, export to CSV

## Requirements
- `GET /expenses` returns all expenses as a JSON array
- Each expense includes: id, amount, category, description, date, created_at
- Frontend renders the expense list on load
- Empty state shown when no expenses exist
- Each expense shows a formatted amount (e.g. $12.50) and category badge

## Acceptance Criteria
- [x] All expenses are displayed on page load sorted by date descending
- [x] Each expense shows amount, category badge, description, and date
- [x] Empty state message shown when there are no expenses
- [x] API returns 200 with an empty array when no expenses exist
- [x] Expenses persist after page refresh

Loading