Milestone Review - bounswe/bounswe2026group9 GitHub Wiki

D6. Milestone Review

D6.1 Project Status

Project Summary

Social Event Mapper reached its MVP milestone as a fully functional, three-platform application: a FastAPI backend deployed on EC2, a Next.js web frontend, and a Kotlin/Jetpack Compose Android app. All core event lifecycle and social features were implemented, tested on the deployed system, and presented in the demo.

Key decisions made during development:

  • Adopted an integration-first testing strategy for the backend: all tests run against a real Supabase PostgreSQL database rather than mocks. This caught several constraint and cascade behaviors that would not surface with SQLite stubs.
  • Chose Supabase as the hosted database rather than self-managing PostgreSQL to reduce infrastructure overhead and take advantage of built-in row-level security.
  • Used Jetpack Compose for the Android UI throughout rather than the legacy XML view system, which required more initial setup but paid off in cleaner state management with ViewModels.
  • Implemented JWT access + refresh token rotation on the backend so mobile clients can stay authenticated across sessions without re-entering credentials.
  • Separated event status transitions (draft β†’ published β†’ updated / cancelled / ended) into an explicit state machine enforced at the service layer, preventing invalid transitions from reaching the database.
  • Decided to skip automated frontend and mobile tests for the MVP milestone and rely on manual validation of the deployed app; automated test suites (Vitest + React Testing Library for web, JUnit + MockK + Compose Testing for Android) are planned for the Final Milestone.

Summary of customer feedback received:

The demo was presented to the Suzan Üsküdarlı and all teaching assistants.

During the demo: The instructor responded positively to the scenario β€” a nature walk bird-watching event β€” and in particular smiled at the "elementary school friendship" detail woven into the narrative. During the mobile demo, she reminded one of the presenter to face the audience and speak louder.

Post-demo feedback from the instructor: She suggested expanding the review/rating system into a more detailed feedback mechanism. Specifically, she proposed that attendees could be asked to fill in structured reviews after an event, including scales for physical difficulty (e.g., how strenuous a walk was), an overall event rating, and free-text fields for hardships encountered or advice for the event organizer. This would make the platform more useful for recurring community events where past-attendee experience guides future participants.

TA feedback: One of the TAs suggested implementing a location search feature during event creation β€” allowing hosts to search for a venue by name rather than placing a pin manually, noting it would be a useful UX improvement. Another TA praised the equipment/materials feature, specifically noting that the "must bring" list (demonstrated via the "bring binoculars" warning in the bird-watching scenario) was well thought out and successfully implemented.

At the close of the session, one of the TA also requested that clicking on a user's avatar/icon anywhere in the app should navigate to that user's profile page β€” a navigation shortcut not yet implemented for all pages at MVP.

Which elicitation questions were most helpful:

Six question clusters produced the clearest signal for requirements:

  1. Q 3.3.1–3.3.3 (visibility modes and private event access) β€” asking explicitly whether private events should be hidden from discovery entirely or shown with limited info, and whether access should use invite links, access codes, or request-to-join, forced a concrete answer that drove one of the most complex feature areas in the system.

  2. Q 2.1.1–2.1.2 (mandatory fields for publishing, including cover image) β€” distinguishing between fields required to save a draft versus fields required to publish gave us the draft/publish separation that underlies the entire event creation flow.

  3. Q 9.2.2–9.2.3 (cancelled event behavior: removed from discovery vs. still visible with label) β€” asking these as two separate questions rather than one revealed that both behaviors are required simultaneously, not as alternatives.

  4. Q 2.4.1 + 2.4.5 (multi-location with one designated primary) β€” asking whether a single event can span multiple venues and whether one must be flagged as primary directly shaped the locations array data model and map pin display logic.

  5. Q 6.3.1 (host profile and rating eligibility) β€” asking specifically who is eligible to rate a host (any user vs. only attendees of an ended event) produced the eligibility rule that became one of the more non-trivial enforcement points in the system.

  6. Q 3.1.1–3.1.2 (roles and per-role permissions) β€” mapping out guest, registered user, and host roles and which actions each can perform gave us a clear permission matrix before any implementation started.

What responses transformed requirements:

  1. Q 3.3.2 β†’ private events visible in discovery with limited info β€” The answer that private events must still appear in map and list views (with a "Private" badge and no detail) rather than being hidden completely transformed the access control design from a simple show/hide into a three-tier visibility model: full detail (authorized), limited preview (unauthorized), hidden (cancelled/draft). This drove conditional rendering logic on both web and mobile for the Request Access / Pending / Denied / Full Detail access states.

  2. Q 2.1.1 β†’ cover image mandatory for publish β€” The answer that at least one cover image is required to publish (not just recommended) transformed event creation from a single-step form into a two-phase flow: create a draft without an image, upload images, then publish. The backend enforces this at the status transition level β€” draft β†’ published is blocked without β‰₯1 image (FRS-2.1.1).

  3. Q 9.2.2 + 9.2.3 combined β†’ dual cancelled event behavior β€” The answers together β€” remove from discovery and keep the event page visible with a cancellation label β€” created a requirement more specific than either answer alone. This became FRS-2.3.3 and FRS-2.3.4, requiring the backend to exclude cancelled events from GET /events results while still returning them on GET /events/{id} with their cancelled status.

  4. Q 3.3.3 β†’ both invite link and request-to-join required β€” The answer that private access must support both token-based invites (host generates a shareable link) and user-initiated access requests (host approves individually) transformed a single access mechanism into a dual system. Each path has independent state (invite: max_uses, expires_at; request: pending/approved/denied), and both grant equivalent access once resolved.

  5. Q 6.3.1 β†’ rating eligibility gated on attendance of an ended event β€” The answer that only users who attended an ended event hosted by that host may rate transformed the rating endpoint from a simple write into one with a prerequisite check (has_attended_ended_event_by_host). This also added the can_rate field to the host profile response so clients can hide the rating UI proactively for ineligible users.


D6.2 Deliverables

List and Status of Deliverables

# Deliverable Status Links
D1 Software Requirements Specification Completed Requirements Β· Elicitation Questions Β· Glossary
D2 Software Design (UML Diagrams) Completed Class Diagram Β· Use Case (Final) Β· Sequence (Final)
D3 Scenarios and Mockups Completed Scenario 1 Β· Scenario 2 Β· Scenario 3
D4 Project Plan, Communication Plan, RAM Completed Implementation Plan Β· Test Plan Β· Communication Plan Β· RAM Β· Team Policies
D5 Pre-release software Completed Release 0.1.0-alpha (includes debug APK)
D5.1 Backend (FastAPI) Completed Deployed to EC2 at https://thesocialeventmapper.social; auth, events, discovery, comments, bookmarks, attendance, invites, access requests, notifications, host profiles, ratings
D5.2 Web Frontend (Next.js) Completed Deployed at https://thesocialeventmapper.social; all MVP screens implemented and manually validated
D5.3 Android Mobile App Completed Debug APK built via GitHub Actions and attached to release; all MVP screens implemented and manually validated on emulator and device
D5.4 CI / DevOps Completed backend-ci.yml (lint + tests on every PR), android-build.yml (APK on push/release), deploy.yml (auto-deploy to EC2 on push to main)
D6 Milestone Review Completed Milestone Review
D7 Individual Contributions Completed Individual Contributions

Feature delivery status:

Feature Area Web Mobile Backend
Auth & User Management (register, login, JWT, refresh, email verification, Google OAuth, account lockout) βœ… βœ… βœ…
Event Creation & Lifecycle (7-step form, draft/publish/update/cancel/end, venue metadata, equipment) βœ… βœ… βœ…
Image Upload & Management (upload, carousel, delete, 10-image limit, resize) βœ… βœ… βœ…
Event Discovery (list/map view, search, category/temporal filters, pagination) βœ… βœ… βœ…
Event Detail & Access Control (full detail, limited preview, private restricted, age gate) βœ… βœ… βœ…
Private Event Flows (invite generation, invite acceptance, access request, approve/reject) βœ… βœ… βœ…
Bookmarking βœ… βœ… βœ…
Attendance (going/interested, capacity enforcement) βœ… βœ… βœ…
Comments (create, list, delete, replies) βœ… βœ… βœ…
Host Profile & Ratings (eligibility: must have attended an ended event by the host) βœ… βœ… βœ…
Notifications (event update/cancellation triggers, list, mark-as-read, unread badge) βœ… βœ… βœ…
Category Management (predefined list, custom category creation) βœ… βœ… βœ…

Reflection on deliverable status and impact on project plan:

The full MVP feature set was delivered on schedule. The most impactful planning decision was treating the backend as the single source of truth for all business logic (access control, lifecycle transitions, capacity enforcement) and building both the web and mobile clients against a single deployed API. This reduced duplication of logic and kept client code focused on presentation.

Two areas required more time than planned: the private event invite/access request flow (more edge cases than anticipated β€” host self-accept, max uses, already-granted idempotency) and the mobile age gate (required device-level DOB storage and conditional navigation). Both were resolved before the demo.

UX design with focus on domain-specific features:

The UI design centers on two domain-specific interaction patterns:

  1. Event lifecycle as a first-class concept: Events surface their status (draft, published, updated, cancelled, ended) prominently in all views. The creation flow uses a 7-step wizard that mirrors how event organizers think about planning β€” basic info β†’ date/time β†’ location β†’ accessibility/venue β†’ categories β†’ images β†’ review. The host receives explicit confirmation at each step and cannot accidentally publish without at least one image.

  2. Access control transparency: Private events appear in discovery with a clear "Private" badge and limited info rather than disappearing entirely. The web and mobile clients expose the correct action per user state β€” Request Access (never requested), Pending (awaiting decision), Access Denied, or Full Detail (approved/invited). Age-restricted events show a date-of-birth collection screen on first encounter rather than a plain error, reducing friction for eligible users.

API documentation with examples:

Full interactive API documentation is available at https://thesocialeventmapper.social/docs (Swagger UI, auto-generated from FastAPI annotations).

Selected endpoint examples:

POST /auth/register
{
  "username": "mehmetkaya",
  "email": "[email protected]",
  "password": "securepassword",
  "date_of_birth": "1995-06-15"
}
β†’ 201: { "user": {...}, "access_token": "...", "token_type": "bearer" }

POST /events
Authorization: Bearer <token>
{
  "title": "Bosphorus Bird Walk",
  "description": "...",
  "start_datetime": "2026-04-12T09:00:00Z",
  "end_datetime": "2026-04-12T12:00:00Z",
  "visibility": "public",
  "is_age_restricted": false,
  "category_ids": ["<uuid>"],
  "locations": [{ "name": "Bebek Park", "latitude": 41.077, "longitude": 29.044, "is_primary": true, "order_index": 0 }]
}
β†’ 201: { "id": "...", "status": "draft", ... }

GET /events?search=bird&temporal_filter=upcoming&page=1&page_size=20
β†’ 200: { "items": [...], "total": 3, "page": 1, "page_size": 20, "total_pages": 1 }

D6.3 Requirements

The following requirements from the Software Requirements Specification were addressed in this milestone. Requirements are referenced by their SRS identifiers (FRU = Functional User Requirements, FRS = Functional System Requirements, NFR = Non-Functional Requirements).

Functional User Requirements (FRU)

Requirement Description Status
FRU-1.1 Registered users can create community events βœ…
FRU-1.1.1 Events require title, description, category, start/end datetime βœ…
FRU-1.1.2 Users can upload one or more images for an event βœ…
FRU-1.1.3 Users can edit events they created βœ…
FRU-1.1.3.1 Only the host can delete their event; deletion requires cancelling or ending first βœ…
FRU-1.1.3.2 Host changes result in either event updated or event cancelled βœ…
FRU-1.1.4 Events can be set public or private βœ…
FRU-1.1.4.1 Private events appear in browse/search with limited info; full detail restricted to host βœ…
FRU-1.1.5 Events classified by selecting from a predefined category catalog βœ…
FRU-1.1.5.1 Users can create a new category entry if no suitable predefined option exists βœ…
FRU-1.1.6 Users can specify event location βœ…
FRU-1.1.6.1 Users can specify multiple ordered locations (route/path) βœ…
FRU-1.1.7 Users can mark an event as 18+ (age-restricted) βœ…
FRU-1.1.8 Users can set an optional attendee limit (capacity) βœ…
FRU-2.1 Users can browse/discover events via map view and list view βœ…
FRU-2.1.1 Users can filter events by category and date/time βœ…
FRU-2.1.2 Users can search for events starting after a specified time βœ…
FRU-3.1 Registered users can view event detail pages for public events βœ…
FRU-3.1.1 Users can bookmark events to view later and receive notifications βœ…
FRU-3.1.2.1 Users can comment under an event βœ…
FRU-3.1.3 Users can rate the event host βœ…
FRU-4.1 Unregistered users cannot view event detail pages βœ…
FRU-4.2 Unregistered users can only browse events in map/list with limited info βœ…
FRU-4.3 Private events visible in browse/search but full details restricted to host βœ…
FRU-5.1 Users can view host profile pages βœ…
FRU-5.1.1 Host profiles show contact info per privacy settings βœ…
FRU-5.1.2 Host profiles show hosted events (past and upcoming) βœ…
FRU-5.1.3 Host profiles show ratings βœ…
FRU-6.1 Users receive notifications when bookmarked/followed events are updated or cancelled βœ…
FRU-6.1.1 Notifications sent on every edit (updated) and cancellation βœ…

Functional System Requirements (FRS)

Requirement Description Status
FRS-1.1 System supports guest access without registration βœ…
FRS-1.2 System allows users to register, sign in, and sign out βœ…
FRS-1.2.1–1.2.6 Auth required for: publish, edit/cancel, comment, bookmark, going; actions associated with user account βœ…
FRS-1.3 Roles of guest, registered user, and admin enforced (guest + registered for MVP) βœ…
FRS-2.1 System validates event data before publishing βœ…
FRS-2.1.1 Required fields enforced before publish: title, description, category, times, location, β‰₯1 image βœ…
FRS-2.1.2 End time must be later than start time βœ…
FRS-2.1.3 Publishing blocked if mandatory fields missing or invalid βœ…
FRS-2.2 System manages event lifecycle states βœ…
FRS-2.2.1 States supported: draft, published, updated, cancelled, ended βœ…
FRS-2.2.2 System automatically marks events as ended once end time has passed βœ…
FRS-2.3 System regulates editing and cancellation behavior βœ…
FRS-2.3.1 Hosts can edit event details before the event starts βœ…
FRS-2.3.2 Modification of time/location blocked after event has started βœ…
FRS-2.3.3 Cancelled events removed from discovery results βœ…
FRS-2.3.4 Cancelled event page remains accessible with cancellation label βœ…
FRS-2.4 Duplicate event creation by same host (same title/time/location) prevented βœ…
FRS-2.5 Optional venue metadata supported βœ…
FRS-2.5.1 Health requirements, age restriction, language fields available βœ…
FRS-2.5.2 Accessibility features: wheelchair, restroom, elevator, seating, captions, quiet-friendly βœ…
FRS-2.6 System manages event categories βœ…
FRS-2.6.1 Predefined category catalog provided βœ…
FRS-2.6.2 Hosts must assign at least one category when publishing βœ…
FRS-2.6.3 Hosts can create custom categories (pending admin approval) βœ…
FRS-3.1 Public and private visibility modes supported βœ…
FRS-3.1.1 Private events appear in discovery with limited preview βœ…
FRS-3.1.2 Full private event details restricted to host βœ…
FRS-3.1.3 Private event access control enforced at the backend level βœ…
FRS-3.2 18+ events labelled; interaction restricted for underage users βœ…
FRS-4.1 Both map and list views provided for discovery βœ…
FRS-4.1.1 Users can switch between map and list views βœ…
FRS-4.2.1 Events prioritised by proximity in time βœ… (sorted by start_datetime)
FRS-4.3.1 Filtering by custom start–end time window supported βœ…
FRS-4.3.2 Quick filters: upcoming, today, this_week βœ…
FRS-5.1 Registered users can bookmark events βœ…
FRS-5.2 Registered users can mark events as Going βœ…
FRS-5.2.1 Hosts can define optional attendee capacity βœ…
FRS-5.2.2 Going blocked once capacity limit reached βœ…
FRS-5.3 Users can remove Bookmark or Going status at any time βœ…
FRS-6.1 Registered users can comment on events βœ…
FRS-6.2 Comments displayed publicly on event page βœ…
FRS-6.3 Host profile pages provided βœ…
FRS-6.3.1–6.3.3 Hosted events, ratings, and contact info (per privacy settings) displayed βœ…
FRS-7.1 Users notified when bookmarked/going events are updated βœ…
FRS-7.2 Users notified immediately when such events are cancelled βœ…
FRS-7.3 Notifications delivered via in-app messaging βœ…
FRS-8.1 Hosts can define multiple locations for an event; one designated primary βœ…
FRS-8.3 Hosts can specify required and optional equipment/materials βœ…
FRS-10.1 Past events retained and marked ended once end time passes βœ…
FRS-10.2 Past events viewable on event detail and host profile pages βœ…
FRS-10.3 Past events excluded from default discovery results βœ…

Requirements deferred to Final Milestone: FRU-1.1.2.1 (online events), FRU-2.1.1.1 (GPS discovery), FRU-3.1.2.2 (P2P messaging), FRS-4.2.2 (distance sort), FRS-4.3.3 (accessibility filters), FRS-4.4 (GPS/default map area preferences), FRS-8.2 (itinerary segments), FRS-9 (reporting & abuse), NFR-01 (2s search), NFR-02 (60s update visibility), NFR-06 (10k events), NFR-07 (structured logging).

Non-Functional Requirements (addressed at MVP)

Requirement Description Status
NFR-03 HTTPS only for all client-server communication βœ… (production deployment)
NFR-04 Backend does not return private event details to unauthorised users, even via direct API calls βœ…
NFR-08 Core pages work on mobile screen widths without broken layout βœ… (manually verified)

D6.4 Testing

D6.4.1 Test Plan & Strategy

Our project has three main components: a Python/FastAPI backend, a Next.js (TypeScript) web frontend, and a Kotlin Android mobile app. Each has its own testing strategy tailored to its role.

Backend Testing Strategy

Our backend testing strategy is integration-first: all tests run against a real Supabase (PostgreSQL) database β€” no mocks for data access, no SQLite stubs. This ensures tests validate actual behavior including constraints, cascades, and query semantics. We mock only external side-effects (email sending, cloud storage uploads, Google OAuth callbacks) to keep tests deterministic and fast.

Test types used:

Type Purpose Example
Unit tests Isolated logic (hashing, JWT encode/decode, datetime validation) TestPassword, TestJWT in test_auth_unit.py; TestValidateEventDatetime in test_event_unit.py; TestGetAffectedUserIds, TestEmitEventNotification in test_notification_emitter_unit.py
API integration tests Full HTTP request β†’ router β†’ service β†’ repository β†’ DB round-trip All endpoint tests (test_events.py, test_discovery.py, test_categories.py, test_images.py, test_comments.py, test_invites.py, test_notifications.py, test_attendances.py, test_bookmarks.py, test_users.py)
Multi-step flow tests End-to-end user journeys spanning multiple endpoints TestFullAuthFlow, TestRefreshTokenRotation, TestEmailVerificationFlow in test_auth_integration.py; test_accept_invite_grants_event_access, test_approve_grants_event_access in test_invites.py

Tools & infrastructure:

  • pytest as test runner (configured in pyproject.toml)
  • FastAPI TestClient (backed by httpx) for HTTP-level testing
  • ruff for static analysis / linting (runs before tests in CI)
  • GitHub Actions CI (backend-ci.yml) β€” triggered on every PR touching backend/**: checkout β†’ Python 3.12 β†’ install deps β†’ ruff check . β†’ pytest tests/ -v
  • Autouse fixtures for cleanup: cleanup_test_users deletes all rows matching test prefixes (testuser_, eventtest_, imgtest_, cattest_, disctest_, attndtest_, bmtest_, cmttest_, invtest_, notiftest_, proftest_) after each test β€” no stale data between runs
  • Mocking: unittest.mock.patch for email sending, Supabase storage upload/delete, and Google OAuth token exchange
Frontend Testing Strategy (Next.js β€” MVP: Automated auth/routing + Manual for feature flows)

The web frontend uses Vitest + React Testing Library for automated unit and component tests covering the auth and routing layer (16 tests, all passing). All other user-facing feature flows were validated through manual testing and visual inspection on the deployed application, including edge cases such as private event access, underage gate behavior, invite token acceptance, and error page rendering.

Additional automated coverage (event discovery, event detail, creation flow, notifications) is planned for the Final Milestone with a frontend-ci.yml GitHub Actions workflow.

MVP validation approach:

Area How validated for MVP
Auth screens Manually tested registration, login, logout, duplicate email error, Google OAuth flow on live deployment
Event discovery Manually verified map/list toggle, search, category and temporal filters, pagination, guest vs. authenticated card differences
Event detail Manually tested full detail view, limited preview for guests, private event restricted view, age gate (underage block + DOB prompt), image carousel, comments, bookmark/going buttons
Event creation Manually stepped through all 7 form steps, draft save, image upload, publish flow, pre-publish validation
Private event flows Manually tested Request Access button, pending state persistence, host invite generation and copy, access request approve/reject
Profile & ratings Manually tested host profile page, hosted events list, rating submission
Notifications Manually verified in-app notification list, unread badge, mark-as-read, event update/cancellation triggers
Error pages Manually navigated to non-existent URLs (404), private events (access denied), and 18+ events as underage user

Planned automated test coverage for Final Milestone:

Type Purpose Tool
Component tests Individual UI components render with correct props and conditional logic Vitest + React Testing Library
User interaction tests Simulate user actions (click, type, submit) and verify resulting UI changes React Testing Library (fireEvent / userEvent)
Navigation tests Screen transitions work correctly (e.g., login β†’ discovery, event card β†’ detail) Next.js routing test utilities
API integration tests API calls are made with correct parameters, responses are handled, errors are displayed Vitest with MSW (Mock Service Worker)
Snapshot tests Catch unintended UI regressions across updates Vitest snapshots

Planned CI: A frontend-ci.yml workflow will be added β€” triggered on PRs touching frontend/**: checkout β†’ Node.js setup β†’ npm install β†’ eslint β†’ vitest --coverage.

Mobile Testing Strategy (Kotlin Android β€” MVP: Manual; Automated: Final Milestone)

For the MVP milestone, the Android app was validated through manual testing on emulator and physical device after each feature implementation. All screens and flows were exercised by hand, including edge cases such as the 18+ block, private event access request, invite deep link acceptance, and error page routing.

Automated tests (JUnit + MockK + Jetpack Compose Testing + android-ci.yml GitHub Actions workflow) are planned for the Final Milestone.

MVP validation approach:

Area How validated for MVP
Auth screens Manually tested registration, login, logout, token persistence (session survives app restart)
Event discovery Manually verified map/list view, search, category and temporal filters, FAB (create event, auth-only)
Event detail Manually tested full detail, limited preview for guests, private event restricted view, age gate (underage + DOB required screens), image carousel, bookmark/going buttons, comments
Event creation Manually stepped through all 7 form steps, date/time picker, image upload, draft save, publish, edit mode pre-fill, cancel and delete confirmation dialogs
Private event flows Manually tested Request Access button with pending/rejected/approved state, host invite management panel, access request approve/reject
Notifications Manually verified notification list, unread badge count in top bar, mark-as-read
Host profile Manually tested host profile page, hosted events list, rating submission
Navigation Manually tested all routes including deep link (sem://invite/{eventId}/{token}), back stack, auth guard

Planned automated test coverage for Final Milestone:

Type Purpose Tool
Unit tests ViewModel logic, repository data mapping, input validation JUnit 5 + MockK
UI tests Screen rendering, user interactions, navigation Jetpack Compose Testing + Espresso
API integration tests Retrofit/OkHttp calls constructed correctly, responses parsed, errors handled JUnit 5 + MockWebServer
Navigation tests Screen transitions, back stack behavior, deep linking Compose Navigation Testing

Planned CI: An android-ci.yml workflow will be added β€” triggered on PRs touching mobile/**: checkout β†’ JDK setup β†’ Gradle build β†’ detekt β†’ ./gradlew test β†’ ./gradlew connectedAndroidTest.


Backend Test Coverage β€” 209 tests across 17 test files

All tests currently implemented and passing. Organized by feature area:

1. Authentication & Authorization (36 tests β€” test_auth.py, test_auth_integration.py, test_auth_unit.py)

Area Tests What is validated
Password hashing 3 bcrypt hash/verify, wrong password rejection, salt randomness
JWT tokens 3 Create/decode, invalid token rejection, expiry enforcement
Registration 6 Success (201), duplicate email/username (409), validation (short password, invalid email, short username β€” 422)
Login 5 Success (200), wrong password (401), non-existent email (401), account lockout after 5 failures (429), deactivated account (403)
Token flow 7 /me with valid/invalid/missing token, refresh via cookie, token rotation (old token revoked), logout, refresh-after-logout fails
Email verification 4 Verify valid token (200), invalid token (400), resend (200), resend-when-already-verified (400)
Integration flows 5 Full register→login→me→refresh→logout, refresh rotation, register→verify→confirm, resend→verify, expired token
Google OAuth 3 New user created, existing user linked, deactivated user rejected

2. Event CRUD & Lifecycle (49 tests β€” test_events.py, test_event_unit.py)

Area Tests What is validated
Create event 12 Draft creation (201), direct-publish blocked (400), venue metadata, equipment, multiple locations, invalid datetime/category (400), duplicates (409), auth required (403), missing fields (422)
Get event 6 Full detail for auth user, limited preview for guest, private event visibility (host vs. others), 404, auto-end on read
Update event 6 Title update (200), published→updated transition, non-host forbidden (403), cancelled event blocked (400), time change after start blocked (400), auth required
Status transitions 7 draft→published without image rejected (400), draft→published with image (200), published→cancelled/ended, invalid transitions (cancelled→published, draft→cancelled — 400), non-host forbidden
Delete event 5 Delete cancelled/ended (200), delete published blocked (400), non-host forbidden (403), auth required
Age restriction 3 Underage user blocked (403), missing DOB blocked, host exempt
Edge cases 5 Updated→cancelled/ended, invalid UUID (422), past start date rejected (400), clear attendee limit
Unit β€” datetime validation 3 Rejects past start by default, rejects end before start, allows past start when explicitly enabled
Unit β€” auto-end logic 2 Marks published past event as ended, leaves future event unchanged

3. Event Discovery & Search (34 tests β€” test_discovery.py)

Area Tests What is validated
Basic listing 9 200 without auth, response shape (items/total/page/page_size/total_pages), published appears, draft hidden, private appears with limited info, past-end-datetime excluded, cancelled excluded, auth user gets full fields, guest vs. auth field differentiation
Sort order 1 Results sorted by start_datetime ascending
Text search 5 Search by title, by description, no results, case-insensitive, excludes non-matching
Category filter 3 Matching events returned, no-match returns empty, invalid UUID rejected (422)
Temporal filter 5 upcoming, today, this_week, far-future exclusion, invalid value rejected (422)
Pagination 8 Default (page=1, size=20), custom size, max 100, min 1, second page, total_pages calculation, empty beyond-total, page=0 rejected
Combined filters 3 search + category, search + temporal, all filters together

4. Categories (9 tests β€” test_categories.py)

Area Tests What is validated
List 4 Returns predefined (β‰₯15), sorted alphabetically, search by name, search no results
Create 5 Custom category (201), duplicate fails (409), no auth (403), empty name (422), custom hidden until approved

5. Image Management (10 tests β€” test_images.py)

Area Tests What is validated
Upload 7 JPEG (201), PNG (201), invalid format rejected (400), non-host forbidden (403), max 10 limit (400), large image resized (≀2048Γ—2048), auth required
Delete 3 Success (200), non-host forbidden (403), nonexistent (404)

6. Comments (20 tests β€” test_comments.py)

Area Tests What is validated
Create comment 7 Success (201), no auth (401), empty text (422), comment on draft event blocked, comment on cancelled event blocked, nonexistent event (404), host can comment own event
List comments 7 Empty list, list with data, newest-first ordering, pagination, no auth required to read, nonexistent event (404), includes user info (username)
Delete comment 6 Owner can delete (200), host can delete others' comments, other user cannot delete (403), nonexistent comment (404), no auth (401), wrong event context

7. Invites & Access Requests (26 tests β€” test_invites.py)

Area Tests What is validated
Create invite 5 Success (201), invite with options (max_uses/expires_at), non-host forbidden (403), public event rejected (400), no auth (401)
Accept invite 6 Success (200), invite grants event access (full detail now visible), invalid token (400), already-granted idempotent (200), host self-accept rejected (400), max uses reached (400)
List invites 2 Host can list (200), non-host forbidden (403)
Create access request 5 Success (201), request notifies host, duplicate blocked (409), public event rejected (400), host self-request rejected (400)
List access requests 2 Host sees pending requests (200), non-host forbidden (403)
Access request decision 6 Approve grants event access, approve confirms full detail visible, deny (200), deny keeps limited access, non-host forbidden (403), already-resolved blocked (400)

8. Attendance & Capacity (1 test β€” test_attendances.py)

Area Tests What is validated
Attendance flow 1 Full flow: mark going, capacity enforcement (second user blocked when limit=1), remove attendance, re-mark going after capacity freed

9. Bookmarks (1 test β€” test_bookmarks.py)

Area Tests What is validated
Bookmark flow 1 Create bookmark (201), list bookmarks, duplicate blocked (409), delete bookmark (200), list empty after deletion

10. User Profiles & Ratings (1 test β€” test_users.py)

Area Tests What is validated
Profile & rating flow 1 Get host profile, rate host (201), rating reflected in profile response, self-rating blocked (400)

11. Notifications (20 tests β€” test_notifications.py, test_notification_emitter.py, test_notification_emitter_unit.py)

Area Tests What is validated
List notifications 6 Empty list, returns items, pagination, ordered newest-first, unauthenticated blocked (401), only own notifications returned
Mark as read 4 Mark single (200), idempotent (already read β†’ 200), not found (404), cannot mark other user's notification
Mark all as read 3 Marks all unread (200), no unread β†’ no-op, only affects own notifications
Emitter integration 4 Event update notifies going user, empty update does not notify, cancel notifies going user, end does not notify
Emitter unit 3 Deduplicates attendees + bookmarkers, excludes host from recipients, returns zero when no non-host recipients

12. Health Check (1 test β€” test_health.py)

Area Tests What is validated
System 1 GET /health returns 200 with database connectivity confirmed

Frontend (Next.js) β€” MVP: 16 automated + manual validation | Additional automation: Final Milestone

For the MVP, the auth and routing layer has 16 Vitest tests covering login, registration, protected routes, guest-only routes, and session management. All other feature flows (event discovery, detail, creation, notifications) were validated manually on the deployed application after each feature was merged. Additional automated test infrastructure (Vitest + React Testing Library + MSW + frontend-ci.yml) will be introduced in the Final Milestone.

Estimated additional automated test total for Final Milestone: ~42 tests (total ~58)

Area Planned Tests What will be validated
Auth screens ~10 Login/registration form validation, error messages (409, 401), token storage, redirect after login, Google OAuth
Event discovery ~12 List renders from API, search filters results, category/temporal chips, pagination, empty state, guest vs. auth card differences
Event detail ~10 Full detail for auth user, limited preview for guest, private restricted view, image carousel, Going/Bookmark buttons, comments, age gate
Event creation ~8 Multi-step form navigation, required field validation, image upload preview, draft save vs. publish flow
Profile ~5 Profile info renders, hosted/past event tabs, rating display, edit form
Notifications ~4 Notification list, unread badge, mark-as-read, empty state
Navigation & routing ~5 Protected routes redirect to login, back navigation, deep links, logout clears session
Error handling ~4 404 page, access denied page, network error display, loading spinners

Mobile (Kotlin Android) β€” MVP: Manual Validation | Automated Tests: Final Milestone

For the MVP, all Android app functionality was validated manually on an emulator and physical device after each feature was merged to main. All screens, flows, and edge cases were exercised by hand including deep links, the 18+ gate, private event access requests, and host action dialogs. Automated test infrastructure (JUnit + MockK + Jetpack Compose Testing + android-ci.yml) will be introduced in the Final Milestone.

Estimated automated test total for Final Milestone: ~58 tests

Area Planned Tests What will be validated
Auth screens ~10 Login/registration validation, API error display, token persistence in DataStore, session restore on relaunch
Event discovery ~12 LazyColumn renders from ViewModel state, search triggers API call, filter chips update query, pagination, empty state, guest vs. auth card differences
Event detail ~10 Full detail composable, limited preview for guest, private restricted view, HorizontalPager image carousel, Going/Bookmark button calls, comment submission, age gate dialog
Event creation ~8 7-step form navigation, required field validation, date/time pickers, image picker, venue metadata, draft save vs. publish
Profile ~5 Profile screen renders, tab switching, rating bar, edit profile
Notifications ~4 Notification list, unread badge, mark-as-read, empty state
Navigation ~5 NavHost routes, auth guard, deep link (sem://invite/{eventId}/{token}), back stack
Offline / error ~4 No-network snackbar, retry, 404/403 error screens, loading shimmer

User Acceptance Criteria Mapping

Each MVP acceptance criterion is mapped to the specific tests that validate it:

MVP Acceptance Criterion Covered By Pass?
Users can register and log in TestRegister (6), TestLogin (5), TestFullAuthFlow (1) βœ…
JWT access + refresh token flow works TestTokenFlow (7), TestRefreshTokenRotation (1) βœ…
Email verification works TestEmailVerification (4), TestEmailVerificationFlow (3) βœ…
Google OAuth sign-in works TestGoogleOAuth (3) βœ…
Users can create events with all required fields TestCreateEvent (12) βœ…
Event images can be uploaded and deleted TestUploadImage (7), TestDeleteImage (3) βœ…
Events require at least one image to publish test_draft_to_published_no_image_rejected, test_draft_to_published_with_image βœ…
Event lifecycle (draft β†’ published β†’ updated β†’ cancelled/ended) TestChangeEventStatus (7), TestUpdatedStatusTransitions (2) βœ…
Only host can edit/delete/change status test_update_not_host_forbidden, test_delete_not_host, test_status_change_not_host βœ…
Guest users see limited event info test_get_event_guest_limited, test_guest_sees_limited_info_auth_sees_full βœ…
Private events visible but restricted test_get_private_event_other_user_limited, test_private_event_appears_with_limited_info βœ…
Age-restricted events enforced TestAgeRestriction (3) βœ…
GET /events returns paginated published events TestListEventsBasic (9), TestListEventsPagination (8) βœ…
Text search across title and description TestListEventsSearch (5) βœ…
Category filter works TestListEventsCategoryFilter (3) βœ…
Temporal filter works (upcoming/today/this_week) TestListEventsTemporalFilter (5) βœ…
Results sorted by start_datetime test_sorted_by_start_datetime βœ…
Past-end events excluded from discovery test_past_end_datetime_not_in_listing βœ…
Category management (predefined + custom) TestListCategories (4), TestCreateCategory (5) βœ…
Auto-end events when time passes TestAutoEndEventIfPast (2) βœ…
Comments β€” create, list, delete TestCreateComment (7), TestListComments (7), TestDeleteComment (6) βœ…
Invite generation and acceptance TestCreateInvite (5), TestAcceptInvite (6), TestListInvites (2) βœ…
Access request flow (request β†’ approve/reject) TestAccessRequests (5), TestAccessDecision (6) βœ…
Attendance and capacity enforcement test_attendance_and_capacity (1) βœ…
Bookmark create and delete test_create_bookmark (1) βœ…
Host profile and ratings test_user_profiles_and_ratings (1) βœ…
Notifications sent on update/cancellation TestUpdateNotification (2), TestCancelNotification (2) βœ…
Notification list, mark-as-read TestListNotifications (6), TestMarkNotificationAsRead (4), TestMarkAllAsRead (3) βœ…
CI pipeline runs lint + tests on every PR backend-ci.yml (ruff β†’ pytest) βœ…

D6.4.2 Test Execution Reports

Full test reports page: GitHub Wiki β€” Test Reports

Backend API (209 tests, 0 failures):

Web App (16 automated tests, 0 failures):

  • XML Report (Vitest): frontend-junit.xml
  • Test files: guest-only-route.test.tsx (2), login-page.test.tsx (4), protected-route.test.tsx (6), register-page.test.tsx (2), session.test.ts (2)

Mobile App (manual validation for MVP; automated reports: Final Milestone):


D6.4.3 Impact Analysis

Coverage:

The 209 backend tests cover every MVP functional requirement end-to-end β€” from HTTP request through business logic to the real PostgreSQL database. Every endpoint in the API has at least one positive path and one negative/error path test. Multi-step flow tests (e.g., register β†’ login β†’ create event β†’ publish β†’ cancel β†’ delete) exercise integration between modules that unit tests cannot catch. The integration-first approach means that passing tests on CI give high confidence that the deployed API behaves correctly.

Frontend and mobile coverage for the MVP was achieved through manual validation on the live deployment. While this is less reproducible than automated tests, it exercised the full UI layer including rendering, navigation, and API contract correctness from the client side.

Bug Detection:

During the testing cycle, the following bugs were found and fixed as a direct result of test failures or manual validation:

  1. Comment replies not displayed on mobile β€” The Gson deserializer silently dropped parent_id and replies fields from CommentDto because they were not declared in the data class. Adding the fields to CommentDto fixed the display of nested replies. Caught during manual mobile testing against the live API.

  2. Host rating eligibility not enforced β€” Initial implementation allowed any authenticated user to rate any host. Tests revealed no attendance check was in place. Fixed by adding has_attended_ended_event_by_host() check in the rating service; the can_rate field was added to the host profile response so clients can hide the rating UI proactively.

  3. Event publish redirect to edit page β€” After publishing an event via the creation flow, the web app redirected to /events/{id}/edit instead of /event/{id}. Caught during manual web testing and fixed by correcting the router.replace call.

  4. Past date not rejected on event creation form β€” The create event form allowed selecting past dates via the datetime-local input. Fixed by adding min attribute to the input and adding explicit validation in validateStep.

  5. Map view exposed age-restricted/private event actions β€” The event popup on the map view showed Going and Request Access buttons without applying the age restriction or private event access checks that the full detail page enforces. Fixed by removing those action buttons from the map popup entirely.

Readiness:

The backend is production-ready from a testing standpoint: 209 tests pass on every CI run against the real database, covering all MVP scenarios. The web and mobile frontends are functionally complete and manually validated. The main gap is the absence of automated frontend and mobile tests, which are scoped for the Final Milestone. The existing CI pipeline (lint + backend tests on every PR, APK build and deploy on merge) provides a solid foundation to add frontend and mobile automation.


D6.5 Planning and Team Process

How the team organized and managed the project:

The team used GitHub Projects (kanban board) to track tasks, with issues created for each feature and bug. Pull requests were required for all changes to main β€” direct commits to main were blocked by branch protection rules. All PRs required at least one review before merge. Commit messages followed the Conventional Commits format (feat:, fix:, docs:, chore:, refactor:).

Work was divided by component ownership while maintaining cross-component awareness:

  • Backend: centralized, with all team members contributing features to the FastAPI application organized by feature module (app/routers/, app/services/, app/repositories/)
  • Frontend (web): Next.js App Router with per-feature component directories
  • Mobile (Android): Jetpack Compose with per-screen ViewModels in ui/ directories

The team communicated primarily via a group chat and weekly sync meetings. Issues were filed on GitHub for tracking; feature branches were named feat/<short-description> and fix/<description>.

Evaluation of tools and processes:

  • GitHub Projects worked well for visualizing work in progress but was less useful for estimating capacity. Transitioning to story-point estimates before the Final Milestone would improve sprint planning.
  • Conventional Commits improved the readability of the git log and made it straightforward to produce changelogs and PR descriptions.
  • Integration-first backend testing (against a real Supabase DB) added test setup complexity but paid for itself by catching constraint violations and cascade behaviors that a mock DB would not have surfaced.
  • Manual frontend/mobile validation was sufficient for MVP but will not scale to the Final Milestone feature set. Automated test suites are a priority for the next sprint.
  • GitHub Actions CI gave the team immediate feedback on regressions β€” the backend CI workflow blocked two PRs that introduced test failures before they reached main.

Links to project plan and process artifacts:

⚠️ **GitHub.com Fallback** ⚠️