From 89d848ee72edb75610c5766f5835d1b55350ee90 Mon Sep 17 00:00:00 2001 From: Stephen Adamson Date: Mon, 23 Feb 2026 01:19:53 +0000 Subject: [PATCH] docs --- README.md | 127 +++++++++++++++++++++++++++- obsidian/Crussell/Crussell Nails.md | 84 ++++++++++++++++-- 2 files changed, 202 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0043f8a..50a0950 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,121 @@ npm run dev # Development server SabreDAV is bundled with PHP‑FPM and Composer. The Docker image installs dependencies automatically during the container start‑up. +## πŸ§ͺ Testing + +### Test Infrastructure + +Crussell has a comprehensive Go testing infrastructure located in `backend/testutils/`: + +| Component | File | Description | +|-----------|------|-------------| +| **Database** | `testutils/testdb/testdb.go` | PostgreSQL test pool, migrations, table truncation | +| **HTTP Helpers** | `testutils/helpers.go` | Request builders, auth helpers, assertions | +| **JWT** | `testutils/jwt/jwt.go` | Test token generation for users/admins | +| **HTTP Client** | `testutils/httptest/client.go` | REST client wrapper with auth support | +| **Fixtures** | `testutils/fixtures/fixtures.go` | Factory functions for test data | +| **Validators** | `internal/validators/validators.go` | ID validation utilities | + +### Test Files + +The project includes 16 test files covering all major handlers: + +``` +backend/ +β”œβ”€β”€ bookings.test # Main booking integration tests +β”œβ”€β”€ portfolio.test # Portfolio system tests +β”œβ”€β”€ handlers/ +β”‚ β”œβ”€β”€ admin/ +β”‚ β”‚ β”œβ”€β”€ bookings_test.go # Admin booking management +β”‚ β”‚ β”œβ”€β”€ today_test.go # Today's view +β”‚ β”‚ β”œβ”€β”€ users_test.go # User management +β”‚ β”‚ └── services_test.go # Service CRUD +β”‚ β”œβ”€β”€ auth/ +β”‚ β”‚ └── auth_test.go # Authentication +β”‚ β”œβ”€β”€ bookings/ +β”‚ β”‚ └── bookings_test.go # User booking flow +β”‚ β”œβ”€β”€ portfolio/ +β”‚ β”‚ └── images_test.go # Image upload/management +β”‚ β”œβ”€β”€ scheduling/ +β”‚ β”‚ └── scheduling_test.go # Availability logic +β”‚ β”œβ”€β”€ services/ +β”‚ β”‚ └── services_test.go # Service eligibility +β”‚ β”œβ”€β”€ user/ +β”‚ β”‚ └── profile_test.go # User profile +β”‚ └── handlers_test.go # Common handler tests +``` + +### Running Tests + +```bash +cd backend + +# Run all tests +go test ./... + +# Run with verbose output +go test -v ./... + +# Run specific test file +go test -v ./handlers/bookings + +# Run tests matching pattern +go test -v -run "TestBooking" ./... +``` + +### Test Database Setup + +Tests use a dedicated PostgreSQL database. Set the connection string via: + +```bash +export TEST_DB_DSN="postgres://user:pass@localhost:5432/crussell_test?sslmode=disable" +go test ./... +``` + +Default DSN: `postgres://myuser:mypassword@localhost:5432/crussell_test?sslmode=disable` + +### Test Utilities Usage + +```go +import ( + "crussell/testutils" + "crussell/testutils/testdb" + "crussell/testutils/fixtures" + "crussell/testutils/jwt" +) + +func TestMyHandler(t *testing.T) { + // Setup test database + cleanup := testutils.SetupTestDB(t) + defer cleanup() + + // Create test data + adminID, _ := fixtures.CreateTestAdminUser(db.DB) + userID, _ := fixtures.CreateTestUser(db.DB) + serviceID, _ := fixtures.CreateTestService(db.DB) + + // Generate tokens + adminToken := jwt.GenerateAdminToken() + userToken := jwt.GenerateUserToken(userID) + + // Make authenticated requests + w := testutils.MakeAdminRequest(router, "GET", "/api/admin/bookings", nil, adminID) + w := testutils.MakeUserRequest(router, "GET", "/api/bookings", nil, userID) + + // Assert results + testutils.AssertStatusCode(t, w, http.StatusOK) + testutils.AssertJSONResponse(t, w, &response) +} +``` + +### Test Conventions + +- All test files use `//go:build test` build tag +- Database is migrated fresh per test run via `testdb.Migrate()` +- Tables are truncated between tests via `testdb.TruncateTables()` +- Test tokens use a fixed secret: `test-secret-key-for-testing-only` +- Fixtures auto-generate unique emails to avoid conflicts + ## πŸ“‚ Environment Variables | Variable | Purpose | Example | @@ -176,8 +291,11 @@ docker compose exec backend sh | Image Metadata Stripping | βœ… | ❌ | EXIF/GPS stripped on upload via `imaging` library | | Profile Pictures | βœ… | βœ… | Upload to separate bucket, cropper, circular display, CalDAV sync | | Auto-Booking Status | βœ… | βœ… | Auto-transition: confirmed β†’ in_progress β†’ completed based on time | -| Simplified Deposits | βœ… | ❌ | `deposits_required` INT on users table (3 default), reduces on payment | +| Simplified Deposits | βœ… | ⚠️ | `deposits_required` INT on users table (3 default), 48h notice, reduces on payment | | Contact Page | βœ… | βœ… | Dynamic data from first admin user via `/api/contact` endpoint | +| Email Verification | βœ… | ❌ | Verification codes, generate/check endpoints | +| Calendar Export | βœ… | ⚠️ | ICS download endpoint, Add to Calendar button (backend complete) | +| Loyalty Stamps | βœ… | βœ… | Backend complete, displayed in account page | ### ⚠️ Partially Complete @@ -352,17 +470,18 @@ grep -rn "console\.log" frontend/src/ --include="*.svelte" --include="*.ts" |------|--------| | `account_role` | `user`, `admin` | | `account_type` | `standard`, `vip`, `guest` | -| `booking_status` | `pending`, `confirmed`, `in_progress`, `completed`, `cancelled`, `no_show` | +| `booking_status` | `pending`, `confirmed`, `in_progress`, `completed`, `client_cancelled`, `we_cancelled`, `re-schedule`, `no_show`, `no_deposit` | | `payment_type` | `deposit`, `full`, `refund` | | `payment_method` | `cash`, `card`, `bank_transfer`, `square` | | `payment_status` | `pending`, `completed`, `failed`, `refunded` | -| `admin_notification_reason` | `pending_booking`, `cancelled_booking`, `rescheduled_booking`, `1_week_no_pay`, `1_month_no_pay`, `affiliate_claim` | +| `admin_notification_reason` | `pending_booking`, `cancelled_booking`, `rescheduled_booking`, `1_week_no_pay`, `1_month_no_pay`, `affiliate_claim`, `late_cancellation`, `no_deposit`, `deposit_paid` | ### Key Tables | Table | Purpose | -|-------|---------| +|-------|--------| | `users` | Customer and admin accounts | +| `verification_codes` | Email verification and password reset codes | | `services` | Salon service catalog | | `bookings` | Appointment records | | `booking_services` | Services per booking (many-to-many) | diff --git a/obsidian/Crussell/Crussell Nails.md b/obsidian/Crussell/Crussell Nails.md index 93cf53d..603cec0 100644 --- a/obsidian/Crussell/Crussell Nails.md +++ b/obsidian/Crussell/Crussell Nails.md @@ -108,11 +108,10 @@ - [x] Book (`/book`) - Full wizard with service selection, date/time, customer details - [x] Portfolio (`/portfolio`) - S3/R2 storage with tag filtering, category filters, pagination, ?img= featured image, admin upload - [x] Today (`/today`) - Admin only, real-time schedule view with auto-status transitions -- [x] Schedule (`/schedule`) - User's upcoming bookings with .ics export -- [x] Account (`/account`) - Profile management, profile picture upload with cropper +- [x] Schedule (`/schedule`) - User's upcoming bookings with .ics export and calendar download button +- [x] Account (`/account`) - Profile management, profile picture upload with cropper, loyalty stamps display - [x] Login (`/login`) - [x] Manage (`/manage`) -- [x] Manage (`/manage`) #### Admin Dashboard (`/admin`) - [x] Auth guard with role check @@ -171,6 +170,74 @@ --- +## Testing Infrastructure + +Crussell has a comprehensive Go testing infrastructure located in `backend/testutils/`: + +### Test Utilities + +| Component | File | Description | +|-----------|------|-------------| +| **Database** | `testutils/testdb/testdb.go` | PostgreSQL test pool, migrations, table truncation | +| **HTTP Helpers** | `testutils/helpers.go` | Request builders, auth helpers, assertions | +| **JWT** | `testutils/jwt/jwt.go` | Test token generation for users/admins | +| **HTTP Client** | `testutils/httptest/client.go` | REST client wrapper with auth support | +| **Fixtures** | `testutils/fixtures/fixtures.go` | Factory functions for test data (users, services, bookings) | +| **Validators** | `internal/validators/validators.go` | ID validation utilities | + +### Test Files + +16 test files covering all major handlers: + +``` +backend/ +β”œβ”€β”€ bookings.test # Main booking integration tests +β”œβ”€β”€ portfolio.test # Portfolio system tests +β”œβ”€β”€ handlers/ +β”‚ β”œβ”€β”€ admin/ +β”‚ β”‚ β”œβ”€β”€ bookings_test.go # Admin booking management +β”‚ β”‚ β”œβ”€β”€ today_test.go # Today's view +β”‚ β”‚ β”œβ”€β”€ users_test.go # User management +β”‚ β”‚ └── services_test.go # Service CRUD +β”‚ β”œβ”€β”€ auth/ +β”‚ β”‚ └── auth_test.go # Authentication +β”‚ β”œβ”€β”€ bookings/ +β”‚ β”‚ └── bookings_test.go # User booking flow +β”‚ β”œβ”€β”€ portfolio/ +β”‚ β”‚ └── images_test.go # Image upload/management +β”‚ β”œβ”€β”€ scheduling/ +β”‚ β”‚ └── scheduling_test.go # Availability logic +β”‚ β”œβ”€β”€ services/ +β”‚ β”‚ └── services_test.go # Service eligibility +β”‚ β”œβ”€β”€ user/ +β”‚ β”‚ └── profile_test.go # User profile +β”‚ └── handlers_test.go # Common handler tests +``` + +### Running Tests + +```bash +cd backend +go test ./... +go test -v ./handlers/bookings +go test -v -run "TestBooking" ./... +``` + +### Test Database + +- DSN: `postgres://myuser:mypassword@localhost:5432/crussell_test?sslmode=disable` +- Override: `export TEST_DB_DSN="..."` +- Uses `testdb.Migrate()` to run init-script.sql +- Tables truncated between tests via `testdb.TruncateTables()` + +### Conventions + +- All test files use `//go:build test` build tag +- Test tokens use fixed secret: `test-secret-key-for-testing-only` +- Fixtures auto-generate unique emails to avoid conflicts + +--- + ## Current Architecture ### Overview Diagram @@ -234,6 +301,9 @@ flowchart TD | GET | `/api/services/eligible-for/{user_id}` | List services filtered by user's age and patch test status (admin only) | | POST | `/api/register` | Create new user account | | POST | `/api/login` | Authenticate and receive JWT | +| POST | `/api/verify/generate` | Generate email verification or password reset code | +| POST | `/api/verify/check` | Verify code (email verification or password reset) | +| GET | `/api/contact` | Get business contact info (from first admin user) | | GET | `/api/scheduling/default-hours` | Get weekly default hours | | GET | `/api/scheduling/exceptional-groups` | List holiday/special hour groups | | GET | `/api/scheduling/working-hours` | Get merged working hours for date range | @@ -245,11 +315,13 @@ flowchart TD |--------|------|-------------| | GET | `/api/user/profile` | Get current user profile | | PUT | `/api/user/profile` | Update profile | +| POST | `/api/user/profile-picture` | Upload profile picture with cropper | | DELETE | `/api/user/account` | Delete account (GDPR) | | GET | `/api/user/loyalty` | Get loyalty stamp count | | GET | `/api/bookings` | List user's bookings | | POST | `/api/bookings` | Create booking | | GET | `/api/bookings/{id}` | Get specific booking | +| GET | `/api/bookings/{id}/calendar` | Download ICS calendar file | | PUT | `/api/bookings/{id}` | Update booking | | DELETE | `/api/bookings/{id}` | Cancel booking | @@ -310,11 +382,12 @@ flowchart TD ```sql account_role: unverified_email | verified_email | admin | guest | affiliate account_type: email | google | microsoft | facebook | guest -booking_status: pending | confirmed | in_progress | completed | client_cancelled | we_cancelled | re-schedule | no_show +booking_status: pending | confirmed | in_progress | completed | client_cancelled | we_cancelled | re-schedule | no_show | no_deposit +verification_purpose: email_verify | password_reset payment_type: deposit | full | tip | balance | partial payment_method: online_square | in_person_card | cash | giftcard | discount payment_status: pending | completed | failed | refunded -admin_notification_reason: pending_booking | cancelled_booking | rescheduled_booking | 1_week_no_pay | 1_month_no_pay | affiliate_claim +admin_notification_reason: pending_booking | cancelled_booking | rescheduled_booking | 1_week_no_pay | 1_month_no_pay | affiliate_claim | late_cancellation | no_deposit | deposit_paid ``` **Suggested additional `admin_notification_reason` values:** @@ -333,6 +406,7 @@ admin_notification_reason: pending_booking | cancelled_booking | rescheduled_boo | Table | Purpose | |-------|---------| | `users` | User accounts with profile data | +| `verification_codes` | Email verification and password reset codes | | `user_social_logins` | Social auth provider links | | `services` | Service offerings | | `user_service_patch_tests` | Patch test tracking |