Skip to content

Final Milestone Test Execution Reports ‐ Mobile

sevdepekkose edited this page May 16, 2026 · 1 revision

This page contains the full verbose test execution output for the Mobile layer, including unit tests and End-to-End (E2E) verification flows.

  1. Unit & Component Tests (Jest) These tests validate individual components, utility functions, and viewmodel logic.
PASS src/services/eventService.test.ts (6.688 s)
  uploadFileToPresignedUrl
    ✓ uploads the local file with the provided method and headers (7 ms)
    ✓ throws a clear error when the upload request fails (20 ms)
    ✓ throws a clear error for unsupported upload methods (6 ms)
    ✓ patches event updates through the versioned update endpoint (1 ms)
    ✓ builds my events from the four backend event-management endpoints (1 ms)
    ✓ falls back safely when event lists are empty or missing
  reconfirmEventParticipation
    ✓ posts to the reconfirm endpoint with bearer auth
  searchLocation
    ✓ returns [] without calling fetch when query is shorter than 2 chars
    ✓ returns [] for whitespace-only queries
    ✓ hits the Photon endpoint with the expected query params
    ✓ does NOT hit the legacy Nominatim endpoint
    ✓ maps Photon GeoJSON business-flows to LocationSuggestion shape
    ✓ combines street and house number into display_name when present
    ✓ skips business-flows with missing or invalid coordinates
    ✓ skips business-flows whose properties produce an empty display_name (1 ms)
    ✓ returns [] on non-2xx HTTP response
    ✓ returns [] when fetch rejects (network error) (3 ms)
    ✓ returns [] when response body is not valid JSON (1 ms)
    ✓ returns [] when response shape is missing business-flows array
    ✓ deduplicates repeated parts in display_name (1 ms)
  reverseGeocode
    ✓ returns null without calling fetch when coords are not finite (1 ms)
    ✓ hits the Photon /reverse endpoint with the expected query params (1 ms)
    ✓ returns a LocationSuggestion with the user-tap coords (not the snapped Photon coords)
    ✓ returns null when Photon returns no business-flows
    ✓ returns null on network error / non-2xx / invalid JSON (1 ms)
    ✓ returns null when properties produce an empty display name
  fetchRoutedGeometry
    ✓ returns null without calling fetch when fewer than 2 waypoints
    ✓ returns null when any waypoint has non-finite coords
    ✓ hits OSRM driving profile with lon,lat;lon,lat coords (1 ms)
    ✓ maps OSRM [lon,lat] coordinates to {lat, lon} pairs in order
    ✓ returns null when OSRM returns a non-Ok code
    ✓ returns null on network failure / non-2xx / invalid JSON
    ✓ returns null when geometry is missing or has fewer than 2 points
    ✓ skips invalid pairs in the geometry

PASS src/viewmodels/profile/useProfileViewModel.test.tsx (7.3 s)
  useProfileViewModel
    ✓ starts in loading state (61 ms)
    ✓ fetches and exposes profile data on mount (14 ms)
    ✓ derives primaryName from display_name when set (20 ms)
    ✓ derives primaryName from username when display_name is null (15 ms)
    ✓ exposes hosted and attended event lists (14 ms)
    ✓ falls back to New when final_score is missing (2 ms)
    ✓ updates unrated labels when language changes without refetching profile data (8 ms)
    ✓ deduplicates attended events returned by multiple endpoints (2 ms)
    ✓ excludes hosted events from the attended tab (13 ms)
    ✓ filters ACTIVE events out of the hosted and attended tabs (3 ms)
    ✓ treats zero-value backend end times as missing (16 ms)
    ✓ sets apiError on API failure (3 ms)
    ✓ sets generic error on unexpected failure (2 ms)
    ✓ sets error when token is null (6 ms)
    ✓ can refresh profile data (36 ms)
    ✓ keeps profile usable when invitations fail to load (91 ms)
    ✓ handles accepting an invitation from profile (45 ms)
    ✓ handles declining an invitation from profile (6 ms)
    ✓ handles equipment addition (7 ms)
    ✓ handles equipment editing (6 ms)
    ✓ handles equipment deletion (3 ms)
    ✓ handles showcase image deletion (4 ms)

PASS src/viewmodels/profile/useEditProfileViewModel.test.tsx
  useEditProfileViewModel
    ✓ starts in loading state (9 ms)
    ✓ populates form fields from fetched profile (4 ms)
    ✓ populates empty strings when profile fields are null (20 ms)
    ✓ updates default location from location search selection (20 ms)
    ✓ saves the raw display_name of a detailed location selection (3 ms)
    ✓ clears the selected default location (28 ms)
    ✓ picks an avatar image from the photo library (2 ms)
    ✓ uploads avatar on save when a new local image is selected (18 ms)
    ✓ omits locked gender and birth date from the update payload (2 ms)
    ✓ updates a field and clears its error (1 ms)
    ✓ validates birth date format on save (1 ms)
    ✓ triggers immediate error for day > 31 (2 ms)
    ✓ triggers immediate error for month > 12 (1 ms)
    ✓ validates month limit (1–12) (5 ms)
    ✓ validates future date limit (10 ms)
    ✓ validates birth date in real-time when 10 characters are reached (2 ms)
    ✓ auto-formats birth date typing into dd.mm.yyyy (1 ms)
    ✓ calls updateMyProfile with correct data on valid save (2 ms)
    ✓ sends empty strings for text fields and null for enums/dates (1 ms)
    ✓ sets apiError on save failure (3 ms)
    ✓ sets error when token is null (3 ms)

PASS src/viewmodels/event/useCreateEventViewModel.test.tsx (7.943 s)
  useCreateEventViewModel
    ✓ starts with today as the default start date and no errors (23 ms)
    ✓ does not include PRIVATE in privacy options
    title validation
      ✓ shows error when title is empty (7 ms)
      ✓ shows error when title is shorter than 10 characters (21 ms)
      ✓ accepts title with exactly 10 characters (23 ms)
    description validation
      ✓ shows error when description is empty (5 ms)
      ✓ shows error when description is shorter than 20 characters (7 ms)
    start date validation
      ✓ shows time validation immediately while typing an invalid hour (2 ms)
      ✓ shows date validation immediately when an impossible day is entered (30 ms)
      ✓ shows error on both fields when start date and time are missing (15 ms)
      ✓ shows error only on date when start date is missing but time is set (3 ms)
      ✓ shows error when start date is in the past (9 ms)
      ✓ accepts a future start date (8 ms)
      ✓ rejects invalid day and time independently (35.21.2030 with 28:00 — example from issue) (12 ms)
      ✓ rejects out-of-range day (35) — only date box is red (3 ms)
      ✓ rejects out-of-range month (21) — only date box is red (3 ms)
      ✓ rejects out-of-range hour (28:00) — only time box is red (8 ms)
      ✓ rejects out-of-range minute (10:70) — only time box is red (5 ms)
      ✓ rejects impossible calendar date (30.02.2030) — only date box is red (12 ms)
    end date validation
      ✓ shows end date error immediately when end time becomes earlier than start (5 ms)
      ✓ shows error on date when end date is before start date (9 ms)
      ✓ clears end date error when end date is updated (10 ms)
      ✓ clears end date error when end time is updated (9 ms)
    error clearing
      ✓ clears start date error when start date is updated (9 ms)
      ✓ clears location error when location query is updated (4 ms)
    capacity constraint
      ✓ shows error when capacity is less than 2 (5 ms)
      ✓ shows error when capacity is 0 (3 ms)
      ✓ shows error when capacity is negative (2 ms)
      ✓ accepts capacity of 2 (7 ms)
      ✓ accepts large capacity value (3 ms)
    age constraint
      ✓ shows error when min age is greater than max age (8 ms)
      ✓ shows error when age is out of range (>120) (7 ms)
      ✓ shows error when age is negative (1 ms)
      ✓ accepts valid age range (7 ms)
      ✓ accepts min-only age (18+) (4 ms)
    constraint limits
      ✓ allows up to 5 total constraints (16 ms)
      ✓ prevents adding more than max total constraints (16 ms)
      ✓ allows more than 2 other constraints when slots are available (19 ms)
      ✓ only allows 1 gender constraint (27 ms)
    tags
      ✓ adds a tag (19 ms)
      ✓ does not add duplicate tags (5 ms)
      ✓ limits to 5 tags (34 ms)
      ✓ removes a tag by index (3 ms)
    submission
      ✓ calls createEvent and returns result on valid form (11 ms)
      ✓ uploads the selected image through the backend flow after event creation (8 ms)
      ✓ shows a clear image error when upload fails after event creation (3 ms)
      ✓ shows a user-friendly message when the image upload network request fails (15 ms)
      ✓ does not call API when validation fails (2 ms)
      ✓ sets apiError on API failure (9 ms)
      ✓ sets generic apiError on unexpected error (4 ms)
      ✓ maps API field errors to form errors (10 ms)
    location
      ✓ searches location suggestions with debounce (1 ms)
      ✓ selects a location from suggestions (1 ms)
      ✓ clears location (2 ms)
    image picking
      ✓ tries safer URI variants and stores a prepared preview image for Android-style picker paths (2 ms)
      ✓ shows an inline error when the selected image cannot be processed (2 ms)
      ✓ shows an inline error and alert when photo permission is denied (1 ms)
  formatDateInput
    ✓ auto-inserts dot after day and month while typing digits
    ✓ limits to dd.mm.yyyy (8 digits)
    ✓ formats when deleting digits
    ✓ strips non-digit characters
  formatTimeInput
    ✓ auto-inserts colon after 2 digits
    ✓ does not auto-insert colon when deleting (1 ms)
    ✓ strips non-digit non-colon characters and auto-formats
    ✓ limits to 5 characters
    ✓ passes through valid partial input
  validateLiveDateInput
    ✓ does not show an error for partial valid input
    ✓ shows an immediate error when day is out of range
    ✓ shows an immediate error when month is out of range
    ✓ uses full date validation when the date is complete
  validateLiveTimeInput
    ✓ does not show an error for partial valid input
    ✓ shows an immediate error when hour is out of range
    ✓ shows an immediate error when minute is out of range
    ✓ uses full time validation when the time is complete
    route mode
      ✓ starts with locationType POINT and an empty routePoints array
      ✓ switches to ROUTE mode and clears the point fields (1 ms)
      ✓ switching back to POINT clears any added route points
      ✓ appends a waypoint via addRoutePointFromCoordinate (1 ms)
      ✓ appends a waypoint via addRoutePointFromSuggestion
      ✓ ignores suggestions with non-numeric coordinates (1 ms)
      ✓ removes a waypoint by index
      ✓ moves a waypoint up with moveRoutePoint(idx, -1) (1 ms)
      ✓ moves a waypoint down with moveRoutePoint(idx, 1)
      ✓ does not crash when moving a waypoint past the boundary (1 ms)
      ✓ shows a validation error when submitting a ROUTE event with fewer than 2 waypoints (11 ms)
      ✓ submits a ROUTE event with route_points and no lat/lon (1 ms)
      ✓ auto-derives address for a ROUTE event when none was typed (1 ms)
      ✓ falls back to coordinates when route waypoint labels are not yet resolved (2 ms)
      ✓ updateRoutePointLabel updates the label of an existing waypoint
      ✓ updateRoutePointLabel is a no-op for out-of-range indices (1 ms)
      ✓ setPointFromCoordinate sets lat/lon and address synchronously
      ✓ setPointFromCoordinate without a label keeps any previously typed query (1 ms)
      ✓ submits a POINT event without route_points (1 ms)
  deriveRouteAddress
    ✓ returns empty string for an empty waypoint list
    ✓ uses the first comma-segment of single-waypoint label
    ✓ joins first and last waypoint short labels with an arrow (1 ms)
    ✓ falls back to lat/lon when no label is present (1 ms)
    ✓ collapses to one segment when first and last short labels match
  normalizePickedImageUri
    ✓ fully decodes Android file URIs until they reach a filesystem path
    ✓ leaves non-encoded file URIs unchanged

PASS src/viewmodels/auth/useForgotPasswordViewModel.test.tsx
  useForgotPasswordViewModel
    ✓ starts on the email step with empty form (2 ms)
    ✓ does not call API when email validation fails
    ✓ advances to otp step after successful OTP request (7 ms)
    ✓ trims email before sending (4 ms)
    ✓ shows apiError on OTP request failure (3 ms)
    ✓ handles unexpected error on OTP request (2 ms)
    ✓ clears field error when email is updated (3 ms)
    ✓ does not call verify API when OTP validation fails (2 ms)
    ✓ advances to reset step after successful OTP verification (5 ms)
    ✓ shows OTP field error on invalid_otp and clears the input (1 ms)
    ✓ shows apiError on OTP verify server error (2 ms)
    ✓ does not call reset API when password validation fails (3 ms)
    ✓ requires confirmed password before reset (1 ms)
    ✓ validates confirmed password matches before reset (1 ms)
    ✓ calls reset API and returns true on success (2 ms)
    ✓ shows apiError on invalid reset token (3 ms)
    ✓ handles unexpected error on reset (2 ms)
    ✓ goes back from otp to email step (3 ms)
    ✓ goes back from reset to otp step (2 ms)

PASS src/components/home/EventMapView.test.tsx (8.482 s)
  EventMapView
    loading state
      ✓ renders a loading indicator and hides the map surface (51 ms)
    error state
      ✓ renders the error message and hides the map surface (31 ms)
    empty state
      ✓ shows the map surface and the empty overlay when no events have coordinates (26 ms)
      ✓ shows the empty overlay when the events list is empty (10 ms)
    marker rendering
      ✓ renders a marker for each event that has valid coordinates (75 ms)
      ✓ does not show the empty overlay when at least one event has coordinates (9 ms)
      ✓ displays the event title in the native callout after a marker is selected (18 ms)
      ✓ uses a category-colored emoji marker for events (11 ms)
      ✓ keeps iOS event marker view tracking disabled after selection (22 ms)
      ✓ lets Android marker tracking settle after the first native snapshot (11 ms)
      ✓ clusters events that are geographically very close at the current zoom (7 ms)
      ✓ splits nearby clusters as the map zooms in (19 ms)
      ✓ zooms toward a cluster when the cluster marker is pressed (16 ms)
      ✓ shows participant count and capacity when both are present (24 ms)
      ✓ shows participant count without capacity when capacity is not set (15 ms)
    location overlays
      ✓ draws the active filter radius as a dashed boundary around the filter center (14 ms)
      ✓ shows current location controls when live location is available (20 ms)
      ✓ centers the map on current location when the locate button is pressed (26 ms)
      ✓ shows search this area after the map center moves away from the filter center (24 ms)
    navigation
      ✓ calls onMarkerPress with the event id when the callout is pressed (27 ms)
      ✓ opens event details from the Android overlay callout (11 ms)
    callout content
      ✓ shows category name in the native callout (26 ms)
      ✓ shows location address when present (12 ms)
      ✓ localizes the callout details hint (31 ms)
      ✓ shows a small event image in the native callout when available (24 ms)
      ✓ falls back to the category placeholder when image prefetch fails (21 ms)
      ✓ falls back to the category placeholder when the callout image fails (20 ms)
      ✓ uses a category placeholder when the callout has no image (22 ms)
      ✓ omits location line when address is not set (23 ms)

PASS src/viewmodels/favorites/useFavoriteLocationsViewModel.test.tsx
  useFavoriteLocationsViewModel
    ✓ loads favorite locations on mount and keeps them sorted alphabetically (21 ms)
    ✓ opens and closes the add modal when the user can still add more locations (1 ms)
    ✓ searches address suggestions with debounce (3 ms)
    ✓ creates a favorite location through the API and keeps the list sorted (2 ms)
    ✓ saves the raw display_name of a detailed suggestion (3 ms)
    ✓ blocks submit with validation errors before calling the API (17 ms)
    ✓ enforces the max 3 rule based on the backend response (5 ms)
    ✓ syncs with the backend when create returns the favorite-location limit error (3 ms)
    ✓ removes a location through the API (5 ms)
    ✓ sets apiError when loading favorite locations fails (11 ms)
    ✓ shows a logged-out error without calling the backend (2 ms)

PASS src/views/event/EventDetailView.test.tsx (8.984 s)
  EventDetailView
    ✓ shows the pending join-request chip and hides the request button (148 ms)
    ✓ shows version history and reconfirm action when attendance needs reconfirmation (50 ms)
    ✓ lets viewers reject attendance reconfirmation by leaving the event (29 ms)
    ✓ renders an empty version-history state when no changes need review (12 ms)
    ✓ renders hero badges in a horizontally scrollable strip (49 ms)
    ✓ hides version history from viewers who are not attending or pending (48 ms)
    ✓ lets hosts open the edit event flow from event detail (17 ms)
    ✓ shows the localized inaccessible state when apiError mentions private events (2 ms)
    ✓ hides the Invite & Manage button for non-host users on private events (25 ms)
    ✓ renders the map and Get Directions button when location coordinates are available (30 ms)
    ✓ does not render the map when location coordinates are missing (14 ms)
    ✓ shows approximate-location banner and hides Get Directions for PROTECTED non-participant (30 ms)
    ✓ hides the approximate-location callout and shows Get Directions for an approved participant (21 ms)
    ✓ hides approximate-location callout for the event host (11 ms)
    ✓ shows approximate-location callout for a pending-request viewer (21 ms)
    ✓ renders meeting instructions when available (23 ms)
    ✓ shows accept and decline actions for invited users (37 ms)
    ✓ renders a Directions to Start button and a Route chip for ROUTE events (17 ms)
    ✓ does not render the map for a ROUTE event with no waypoints (14 ms)

PASS src/viewmodels/event/useEventDiscussionViewModel.test.ts
  useEventDiscussionViewModel — initial load
    ✓ loads discussion and review comments on mount (56 ms)
    ✓ passes token to listEventComments (3 ms)
    ✓ works without a token (unauthenticated) (5 ms)
    ✓ handles fetch failure gracefully without throwing (55 ms)
  useEventDiscussionViewModel — pagination
    ✓ appends more discussions on loadMoreDiscussions (55 ms)
    ✓ does not load more when hasNext is false (57 ms)
  useEventDiscussionViewModel — replies
    ✓ loads replies for a parent comment (54 ms)
    ✓ appends more replies on loadMoreReplies (56 ms)
  useEventDiscussionViewModel — submitDiscussionComment
    ✓ prepends the new comment to discussions list on success (54 ms)
    ✓ sets discussionError when createDiscussionComment fails (58 ms)
    ✓ does nothing when message is empty (56 ms)
    ✓ dismissDiscussionError clears the error (56 ms)
  useEventDiscussionViewModel — submitReply
    ✓ appends the reply to repliesMap and increments reply_count (55 ms)
  useEventDiscussionViewModel — submitReview
    ✓ upserts the review and updates the reviews list (54 ms)
    ✓ replaces existing review from same user instead of appending (55 ms)
    ✓ does nothing when rating is 0 (54 ms)
    ✓ sets reviewError on failure and dismissReviewError clears it (55 ms)
  useEventDiscussionViewModel — refresh
    ✓ reloads comments on refresh (108 ms)

PASS src/theme/ThemeContext.test.tsx
  ThemeProvider
    ✓ renders nothing before the stored preference is resolved (2 ms)
    ✓ renders children once the stored preference is resolved (8 ms)
    ✓ applies lightTheme when system is light and no stored preference (11 ms)
    ✓ applies darkTheme when system is dark and no stored preference (6 ms)
    ✓ applies the stored preference "dark" regardless of system scheme (8 ms)
    ✓ applies the stored preference "light" regardless of system scheme (6 ms)
    ✓ ignores an invalid stored value and falls back to system (6 ms)
    ✓ still hydrates when SecureStore.getItemAsync rejects (6 ms)
  setThemePreference
    ✓ switches to dark theme when preference is set to "dark" (23 ms)
    ✓ switches to light theme when preference is set to "light" (6 ms)
    ✓ returns to system scheme when preference is set to "system" (34 ms)
    ✓ persists the preference even when SecureStore.setItemAsync rejects (14 ms)
  useTheme outside provider
    ✓ throws an error when called outside ThemeProvider (37 ms)

PASS src/views/event/CreateEventView.test.tsx
  CreateEventView
    ✓ renders picker-based date and time controls with image upload messaging (106 ms)
    ✓ lets Android handle keyboard resizing without shrinking the React tree (38 ms)
    ✓ opens the start pickers and allows today as the minimum date (67 ms)
    ✓ uses the selected start date as the inclusive minimum for end date picker (59 ms)
    ✓ clears optional end date and time together from the screen action (35 ms)
    ✓ renders correct helper text for each privacy level (81 ms)
    ✓ allows toggling audience attributes (74 ms)
    ✓ returns to the previous screen after creating an event successfully (51 ms)
    ✓ falls back to home after creation when there is no previous screen (69 ms)

PASS src/views/favorites/FavoriteEventsTab.test.tsx
  FavoriteEventsTab
    ✓ renders the loading state while favorite events are being fetched (4 ms)
    ✓ renders the empty state when the user has no favorite events (5 ms)
    ✓ renders an error banner without the empty state when loading fails (2 ms)
    ✓ renders favorite events from the dedicated favorites payload and navigates on press (2 ms)
    ✓ passes the optional privacy level through when the favorites response includes it (1 ms)
    ✓ passes the optional location address through when the favorites response includes it (1 ms)

PASS src/viewmodels/event/useEditEventViewModel.test.tsx
  useEditEventViewModel
    ✓ prefills the edit form from the current event detail (74 ms)
    ✓ builds a versioned update request and refreshes the event after saving (60 ms)
    ✓ blocks capacity below approved plus pending participants before calling the API (56 ms)
    ✓ uploads a selected image without patching event fields (61 ms)

PASS src/services/commentService.test.ts
  listEventComments
    ✓ fetches comments without auth when no token provided (1 ms)
    ✓ fetches comments with auth when token provided
    ✓ builds correct query string with pagination params
    ✓ throws ApiError on non-2xx response (1 ms)
  listCommentReplies
    ✓ fetches replies for a parent comment
    ✓ passes cursor and limit in query string
  createDiscussionComment
    ✓ posts a new top-level discussion comment
    ✓ posts a reply with parent_id
    ✓ throws ApiError when write is not allowed (1 ms)
  upsertReviewComment
    ✓ posts a review with rating and message
    ✓ throws ApiError when host tries to review own event

PASS src/views/profile/ProfileView.test.tsx
  ProfileView
    ✓ renders invitations as a profile section with actions (113 ms)
    ✓ previews only one invitation on profile and links to the full invitations page (36 ms)
    ✓ dismisses the keyboard when tapping the equipment modal surface (87 ms)

PASS src/views/favorites/FavoriteLocationsTab.test.tsx
  FavoriteLocationsTab
    ✓ renders the loading state while favorite locations are being fetched (14 ms)
    ✓ renders the empty state when the user has no saved favorite locations (3 ms)
    ✓ renders an error state with retry when loading favorite locations fails (4 ms)
    ✓ shows the backend-backed count and limit banner when the user has three locations (10 ms)
    ✓ renders the add location modal inside a safe area wrapper (10 ms)

PASS src/views/event/EditEventView.test.tsx
  EditEventView
    ✓ renders the current event values in the supported edit form (90 ms)
    ✓ lets hosts choose a cover image from the edit form (37 ms)
    ✓ shows confirmation for critical updates and navigates to refreshed detail on success (139 ms)
    ✓ communicates API failures in the edit screen (27 ms)

PASS src/views/auth/RegisterView.test.tsx
  RegisterView
    ✓ renders account details and updates fields from user input (19 ms)
    ✓ lets users clear a selected gender chip (40 ms)
    ✓ verifies OTP, stores the session, and navigates home (66 ms)
    ✓ edits OTP and returns to the details step (6 ms)
    ✓ routes to sign in from details without submitting registration (5 ms)
    ✓ does not navigate when OTP verification returns no session (12 ms)
    ✓ disables details controls while registration is loading (20 ms)

PASS src/components/home/LocationPickerPanel.test.tsx
  LocationPickerPanel
    ✓ renders the default option and favorite locations as ready-to-use choices (13 ms)
    ✓ shows a loading state while favorite locations are being fetched (15 ms)
    ✓ shows an empty state when the user has no favorite locations (4 ms)
    ✓ shows an error state with retry when favorite locations fail to load (13 ms)
    ✓ shows only search results while the user is searching (4 ms)

PASS src/views/ticket/TicketScanView.test.tsx
  TicketScanView
    ✓ renders the loading state (5 ms)
    ✓ renders an open failure with retry and back actions (9 ms)
    ✓ blocks non-hosts from the scanner UI (17 ms)
    ✓ renders a camera permission prompt and requests permission (16 ms)
    ✓ submits scanned QR data and pauses duplicate scan callbacks (17 ms)
    ✓ shows an accepted scan result and clears it when scanning another ticket (10 ms)

PASS src/viewmodels/auth/useRegisterViewModel.test.tsx
  useRegisterViewModel
    ✓ starts on details step with empty form (6 ms)
    ✓ does not call API when validation fails on submit details (3 ms)
    ✓ requires gender and birth date before requesting OTP (4 ms)
    ✓ sets email and username errors when check-availability returns TAKEN (8 ms)
    ✓ requests OTP and moves to otp step when availability is clear (7 ms)
    ✓ sets apiError when check-availability throws ApiError (10 ms)
    ✓ returns session when OTP verify succeeds (14 ms)
    ✓ maps invalid_otp ApiError to otp field and clears otp input (7 ms)
    ✓ goBack returns from otp to details (2 ms)

PASS src/components/events/HostManagementModals.test.tsx
  host management sheets
    ✓ renders join request management labels from i18n (16 ms)
    ✓ renders invitation management labels from i18n (14 ms)

PASS src/components/home/FiltersBottomSheet.test.tsx
  FiltersBottomSheet
    ✓ renders the frontend sort options (19 ms)
    ✓ shows the selected sort option and calls back when another one is pressed (31 ms)
    ✓ allows toggling audience filters (39 ms)

PASS src/views/home/HomeView.test.tsx
  HomeView
    ✓ silently refreshes events when Home regains focus after the initial mount (9 ms)

PASS src/views/auth/ForgotPasswordView.test.tsx
  ForgotPasswordView
    ✓ renders the email step, updates email, and submits OTP request (7 ms)
    ✓ routes back to sign in from the email step (10 ms)
    ✓ edits OTP, verifies it, and returns to email when requested (4 ms)
    ✓ resets the password and navigates to sign in on success (78 ms)
    ✓ keeps the user on reset step when password reset fails (9 ms)
    ✓ disables the active input and shows progress while loading (20 ms)

PASS src/views/ticket/EventActionsView.test.tsx
  EventActionsView
    ✓ renders the loading state (7 ms)
    ✓ renders an error state with retry and back actions (3 ms)
    ✓ lets hosts open scanner, edit event, view full event, and open host profile (25 ms)
    ✓ lets attendees open their ticket when a ticket is available (6 ms)

PASS src/views/events/MyEventsView.test.tsx
  MyEventsView
    ✓ renders the my events page and event cards (36 ms)
    ✓ opens the event actions screen when an event card is pressed (9 ms)
    ✓ updates the selected status tab when a segment is pressed (18 ms)
    ✓ renders the empty state for the selected status (8 ms)
    ✓ shows summary fallbacks when /me does not provide location or attendee count (11 ms)
    ✓ renders a retryable error state (6 ms)

PASS src/views/invitation/InvitationsView.test.tsx
  InvitationsView
    ✓ renders loading state (19 ms)
    ✓ renders empty state when no invitations (6 ms)
    ✓ renders list of invitations (3 ms)
    ✓ triggers accept and decline actions (6 ms)

PASS src/viewmodels/event/useEventDetailViewModel.test.tsx (11.793 s)
  resolveConstraintViolation
    ✓ returns null when event has no gender or age constraints (3 ms)
    ✓ returns null when preferred_gender is set but user gender is missing
    ✓ returns null when preferred_gender is set but user gender is blank or whitespace (13 ms)
    ✓ returns null when user matches (lowercase or API uppercase wire format)
    ✓ returns a message when user gender does not match preferred_gender (1 ms)
    ✓ returns null when minimum_age is set but birth_date is missing or blank
    ✓ returns a message when user is under minimum_age
    ✓ joins gender and age messages with · when both fail
  useEventDetailViewModel
    initial state
      ✓ starts in loading state with no event data (15 ms)
    fetching event
      ✓ loads event detail on mount and sets viewer context (59 ms)
      ✓ normalizes backend APPROVED participation status to JOINED (56 ms)
      ✓ sets apiError when fetch fails (57 ms)
      ✓ retry re-fetches the event (60 ms)
    isQuotaFull
      ✓ is false when approved count is below capacity (54 ms)
      ✓ is true when approved count meets capacity (57 ms)
      ✓ is false when capacity is null (unlimited) (54 ms)
    handleToggleFavorite
      ✓ calls removeFavorite and decrements count when currently favorited (58 ms)
      ✓ calls addFavorite and increments count when currently not favorited (60 ms)
      ✓ rolls back optimistic favorite change when API fails (55 ms)
      ✓ initialises isFavorited from viewer_context (55 ms)
    handleJoin
      ✓ calls joinEvent, refreshes event detail, and reflects JOINED status (56 ms)
      ✓ does not show full loading screen during post-join refresh (58 ms)
      ✓ sets actionError when joinEvent returns an ApiError (58 ms)
      ✓ sets generic actionError on unknown join failure (56 ms)
    join request modal
      ✓ opens and closes the modal (54 ms)
      ✓ clears message and error when closing the modal (56 ms)
      ✓ updates joinRequestMessage (55 ms)
    handleRequestJoin
      ✓ calls requestJoinEvent with the message and updates status to PENDING (58 ms)
      ✓ sends null message when the input is blank (58 ms)
      ✓ trims whitespace-only message and sends null (65 ms)
      ✓ sets actionError and keeps modal open when request fails (54 ms)
    invitation actions
      ✓ accepts an invitation and refreshes the event as joined (56 ms)
      ✓ declines an invitation and hides the event detail (58 ms)
    reconfirmation actions
      ✓ reconfirms pending participation and refreshes event detail (55 ms)
      ✓ shows API errors when reconfirmation fails (57 ms)
      ✓ maps backend pending join-request status into the mobile pending state (54 ms)
    constraintViolation
      ✓ is null when the event has no constraints (53 ms)
      ✓ is null when user gender is unknown (null) even if event has preferred_gender (54 ms)
      ✓ is null when user gender matches preferred_gender (case-insensitive) (55 ms)
      ✓ is null when session UserSummary.gender is uppercase MALE (API wire format) (55 ms)
      ✓ is non-null when user gender does not match preferred_gender (52 ms)
      ✓ is null when user birth_date is unknown even if event has minimum_age (56 ms)
      ✓ is null when session UserSummary.birth_date is set and user meets minimum age (53 ms)
      ✓ is non-null when user is under the minimum age (57 ms)
      ✓ combines both gender and age violations into one message (52 ms)
    Host actions
      ✓ handleApproveRequest calls api and refreshes event detail (55 ms)
      ✓ handleRejectRequest calls api and refreshes event detail (56 ms)
      ✓ handleCancelEvent calls api and refreshes event detail (57 ms)
      ✓ handleCancelEvent sets global actionError if it fails (54 ms)
    canLeave
      ✓ is true when user is a joined participant on an active event (55 ms)
      ✓ is true when user is a joined participant on an in-progress event with future end_time (54 ms)
      ✓ is false when the user is the host (57 ms)
      ✓ is false when user is not a participant (57 ms)
      ✓ is false when event is canceled (57 ms)
      ✓ is false when event is completed (56 ms)
      ✓ is false when event end_time has passed (54 ms)
    handleLeaveEvent
      ✓ calls leaveEvent API, refreshes detail, and sets success_left for post-start leave (53 ms)
      ✓ sets actionState to idle for pre-start leave (backend allows rejoin) (56 ms)
      ✓ sets actionError with API message when leave fails (56 ms)
      ✓ sets generic actionError on unknown leave failure (56 ms)
    rating actions
      ✓ submits viewer rating and refreshes event detail (55 ms)
      ✓ maps viewer rating errors from the backend (57 ms)
      ✓ submits participant rating and refreshes host lists (57 ms)
      ✓ stores participant rating errors on the matching participant (56 ms)
    invitations
      ✓ loads invitations when modal is opened (120 ms)
      ✓ successfully invites users and refreshes list (56 ms)
      ✓ throws error with specific message when some usernames are invalid (96 ms)
      ✓ throws error with specific message when users are already invited (54 ms)
      ✓ searches for users when query changes (10 ms)
    Join Request Image Attachment
      ✓ picks an image successfully (55 ms)
      ✓ removes the selected image (61 ms)
      ✓ uploads image and sends confirm token on handleRequestJoin (59 ms)
    handleCancelJoinRequest
      ✓ calls withdrawJoinRequest, clears status, and refreshes event (54 ms)
      ✓ handles 409 conflict by refreshing and showing an error (55 ms)
    handleRevokeInvitation
      ✓ calls revokeInvitation and refreshes host context (56 ms)
    Event Reporting
      ✓ manages reporting state and handles success (58 ms)
      ✓ handles duplicate report error (59 ms)
      ✓ supports optional image upload for reporting (57 ms)

PASS src/services/api.test.ts
  api auth refresh handling
    ✓ refreshes and retries an authenticated request after a 401 response (17 ms)
    ✓ throws immediately on 401 when there is no refresh token available (75 ms)
    ✓ throws after retry if the retried request also returns 401 (17 ms)
    ✓ propagates the error when the refresh request itself fails and clears the session (6 ms)

PASS src/viewmodels/ticket/useTicketViewModel.test.tsx
  useTicketViewModel
    ✓ shows the backend qr access reason immediately when ticket access is not yet eligible (13 ms)
    ✓ fetches qr token automatically via polling when ticket is active (7 ms)
    ✓ polls for a new token after 10 seconds (3 ms)
    ✓ checks ticket status every 2 seconds while the live ticket is open (9 ms)
    ✓ handles refresh by resetting state and re-fetching (16 ms)

PASS src/viewmodels/auth/useLogoutViewModel.test.tsx
  useLogoutViewModel
    ✓ starts with isLoggingOut false and no error (1 ms)
    ✓ calls onLoggedOut immediately when refreshToken is null (1 ms)
    ✓ calls logout API with refresh_token and invokes onLoggedOut on success (1 ms)
    ✓ still calls onLoggedOut when server returns 401 (1 ms)
    ✓ shows API error message and does not call onLoggedOut on non-401 API error (3 ms)
    ✓ shows generic error message on network failure (2 ms)
    ✓ clears previous error when handleLogout is called again (2 ms)
    ✓ shows error and blocks logout on 403 forbidden (2 ms)

PASS src/viewmodels/auth/useLoginViewModel.test.tsx
  useLoginViewModel
    ✓ starts with empty form and no errors (2 ms)
    ✓ does not call API when validation fails (1 ms)
    ✓ clears field error and apiError when a field is updated (1 ms)
    ✓ returns session on successful login (1 ms)
    ✓ sets apiError on invalid credentials (401) (2 ms)
    ✓ localizes invalid credentials API errors in Turkish (6 ms)
    ✓ sets apiError on rate limit (429) (2 ms)
    ✓ sets generic apiError on unexpected errors (2 ms)
    ✓ returns null when login fails (4 ms)

PASS src/viewmodels/ticket/useTicketScanViewModel.test.tsx
  useTicketScanViewModel
    ✓ loads the event and exposes host scan access (69 ms)
    ✓ shows a login error without calling the event endpoint when auth is missing (6 ms)
    ✓ trims and submits a QR token successfully (64 ms)
    ✓ validates empty QR input before submitting (55 ms)
    ✓ surfaces API scan failures and clears them with clearResult (56 ms)

PASS src/viewmodels/profile/useChangePasswordViewModel.test.tsx
  useChangePasswordViewModel
    ✓ starts with empty form and no errors (2 ms)
    ✓ validates required fields (1 ms)
    ✓ validates password match (2 ms)
    ✓ validates new password is different from current (2 ms)
    ✓ handles successful password change (2 ms)
    ✓ handles wrong current password (401) (2 ms)
    ✓ handles generic API errors (1 ms)

PASS src/viewmodels/notifications/useNotificationsViewModel.test.tsx
  useNotificationsViewModel
    ✓ loads notifications on mount (56 ms)
    ✓ loads more notifications with the next cursor (55 ms)
    ✓ marks a notification read optimistically (55 ms)
    ✓ restores notification state when mark read fails (56 ms)
    ✓ marks all notifications read (56 ms)
    ✓ restores notification state when mark all read fails (57 ms)
    ✓ removes a notification after delete succeeds (55 ms)

PASS src/firebase/usePushMessaging.test.tsx
  usePushMessaging
    ✓ registers the FCM token when an auth token is available (55 ms)
    ✓ does not request or register for push while disabled (3 ms)
    ✓ syncs a previously acquired FCM token after login (57 ms)
    ✓ unregisters the installation when the auth token is cleared (107 ms)
    ✓ unregisters the installation when push notifications are disabled (109 ms)
    ✓ normalizes initial notification payloads for open handling (55 ms)

PASS src/viewmodels/event/useMyEventsViewModel.test.tsx
  useMyEventsViewModel
    ✓ loads my events on mount and decorates attended ticket data (63 ms)
    ✓ filters events when the selected status changes (75 ms)
    ✓ shows an auth-specific error when the user is logged out (4 ms)
    ✓ surfaces a retryable error when loading fails (58 ms)

PASS src/viewmodels/invitation/useInvitationsViewModel.test.ts
  useInvitationsViewModel
    ✓ fetches pending invitations on mount and ignores past invitations (14 ms)
    ✓ handles errors during fetch (3 ms)
    ✓ removes invitation after successful accept (9 ms)
    ✓ removes invitation after successful decline (4 ms)

PASS src/views/profile/ChangePassword.test.tsx
  ChangePasswordView
    ✓ renders password fields, validation feedback, and visibility toggles (47 ms)
    ✓ submits through the view model and returns after a successful change (11 ms)
    ✓ disables submission while loading and surfaces banner messages (22 ms)

PASS src/views/auth/LoginView.test.tsx
  LoginView
    ✓ renders validation feedback and lets users edit credentials (81 ms)
    ✓ stores the returned session and navigates home after sign in (69 ms)
    ✓ routes secondary auth actions without submitting (10 ms)
    ✓ disables inputs and links while signing in (28 ms)

PASS src/views/notifications/NotificationsView.test.tsx
  NotificationsView
    ✓ renders notifications grouped in sections (17 ms)
    ✓ renders accepted and declined invitation notification labels (16 ms)
    ✓ shows empty state (6 ms)
    ✓ navigates back (19 ms)
    ✓ localizes notification relative time in Turkish (10 ms)

PASS src/components/home/HomeHeader.test.tsx
  HomeHeader
    ✓ renders the SEM logo on the left (19 ms)
    ✓ calls onPressNotifications when the bell button is pressed (35 ms)
    ✓ calls onPressThemeToggle when the theme button is pressed (2 ms)
    ✓ shows a moon icon in light mode and a sun icon in dark mode (12 ms)
    ✓ theme toggle is the rightmost header action (7 ms)
    ✓ shows a badge when unreadNotificationCount is greater than zero (8 ms)
    ✓ caps the badge at 99+ (3 ms)
    ✓ does not show a badge when unreadNotificationCount is zero (2 ms)

PASS src/views/ticket/TicketView.test.tsx
  TicketView
    ✓ renders a larger 260px QR code and a circular timer (42 ms)
    ✓ shows a refreshing indicator when secondsRemaining reaches 0 (5 ms)
    ✓ shows error panel when apiError exists (7 ms)

PASS src/utils/notificationPresentation.test.ts
  notificationPresentation
    ✓ marks supported participation notifications as dedicated (1 ms)
    ✓ builds a dedicated invitation presentation (1 ms)
    ✓ builds a dedicated rejection presentation with cooldown metadata (1 ms)
    ✓ builds a dedicated submitted presentation for host
    ✓ builds accepted and declined invitation presentations for the host
    ✓ falls back to generic presentation for unsupported types (1 ms)

PASS src/utils/validators.test.ts
  validateEmail
    ✓ returns null for a valid email (1 ms)
    ✓ rejects empty or whitespace-only (5 ms)
    ✓ rejects invalid format
    ✓ rejects when longer than 320 chars
  validateOtp
    ✓ returns null for six digits (1 ms)
    ✓ rejects empty
    ✓ rejects wrong length or non-digits
  validateUsername
    ✓ returns null for valid username
    ✓ rejects empty
    ✓ rejects invalid length
    ✓ rejects invalid characters
  validatePassword
    ✓ returns null for valid length
    ✓ rejects empty
    ✓ rejects too short or too long
  validatePhoneNumber
    ✓ returns null when empty (optional)
    ✓ returns null for plausible numbers
    ✓ rejects too long
    ✓ rejects invalid characters
  validateBirthDate
    ✓ returns null when empty (optional)
    ✓ returns null for valid past date
    ✓ rejects wrong format
    ✓ rejects future dates

PASS src/components/home/CategoryChips.test.tsx
  CategoryChips
    ✓ renders selected category chips with remove affordances (5 ms)
    ✓ toggles categories and clears all selected categories (11 ms)
    ✓ localizes quick-select category labels and accessibility labels (3 ms)

PASS src/components/events/EventDiscussionSection.test.tsx
  EventDiscussionSection localization
    ✓ localizes reply toggles and relative timestamps in Turkish (35 ms)

PASS src/viewmodels/favorites/useFavoriteEventsViewModel.test.tsx
  useFavoriteEventsViewModel
    ✓ loads favorite events on mount from the dedicated favorites endpoint (55 ms)
    ✓ refresh reloads the favorite events list from the favorites endpoint (56 ms)
    ✓ loadMore is a no-op because the favorites endpoint is not paginated (56 ms)
    ✓ remove favorite calls the API and removes the event locally (55 ms)
    ✓ surfaces a helpful apiError when loading fails (56 ms)

PASS src/viewmodels/profile/usePublicProfileViewModel.test.tsx
  usePublicProfileViewModel
    ✓ fetches and exposes public profile data on mount (4 ms)
    ✓ handles API errors gracefully (10 ms)
    ✓ can refresh data (6 ms)
    ✓ derives avatar initial correctly (3 ms)

PASS src/viewmodels/home/useHomeViewModel.viewMode.test.ts
  useHomeViewModel – viewMode toggle
    ✓ starts in MAP mode (3 ms)
    ✓ switches to LIST mode when toggleViewMode is called once (2 ms)
    ✓ switches back to MAP mode when toggleViewMode is called a second time (4 ms)
    ✓ exposes activeLocation as numeric lat/lon based on the resolved location (2 ms)

PASS src/views/profile/EditProfileView.test.tsx
  EditProfileView
    ✓ replaces to the profile tab after a successful save (63 ms)
    ✓ does not navigate away when save fails (11 ms)

PASS src/services/sessionManager.test.ts
  sessionManager
    ✓ rotates tokens once and shares a single in-flight refresh request (20 ms)
    ✓ clears the stored session when refresh fails terminally (9 ms)

PASS src/services/notificationService.test.ts
  notificationService
    ✓ lists notifications through the authenticated feed endpoint
    ✓ lists unread notifications when requested
    ✓ fetches unread count
    ✓ marks notifications as read
    ✓ deletes one notification or the whole visible feed

PASS src/utils/eventDate.test.ts
  getAutoCompletionDaysLeft
    ✓ returns null for ACTIVE events
    ✓ returns null for COMPLETED events
    ✓ returns null for CANCELED events
    ✓ returns null for IN_PROGRESS events that have an end_time
    ✓ returns null when event started less than 53 days ago
    ✓ returns null when event started 60 or more days ago
    ✓ returns 7 when event started exactly 53 days ago
    ✓ returns 1 when event started exactly 59 days ago (1 ms)
    ✓ returns correct days left for day 55
    ✓ treats null end_time the same as undefined
    ✓ accepts a custom now parameter (1 ms)

PASS src/services/pushDeviceService.test.ts
  pushDeviceService
    ✓ registers the installation fcm token through the authenticated API (1 ms)
    ✓ unregisters the installation through the authenticated API

PASS src/utils/eventFavoriteCount.test.ts
  getFavoriteCountForDisplay
    ✓ uses API favorite_count when present
    ✓ shows 0 when not favorited and no count
    ✓ shows at least 1 when favorited but count missing or zero (legacy discovery)
    ✓ uses non-zero count when favorited

PASS src/views/favorites/FavoritesView.test.tsx
  FavoritesView
    ✓ renders favorite events by default (6 ms)
    ✓ switches between events and locations tabs (5 ms)

PASS src/utils/eventStatus.test.ts
  eventStatus
    ✓ formats known and unknown backend statuses for display (1 ms)
    ✓ returns distinct colors for supported statuses with a safe fallback (1 ms)
    ✓ hides only ACTIVE events from profile lists

PASS src/utils/notificationRouting.test.ts
  resolveNotificationRoute
    ✓ routes private invitation notifications to the event detail route
    ✓ maps backend event deep links to the mobile event route
    ✓ falls back to event_id metadata
    ✓ routes notification links to the inbox (1 ms)
    ✓ returns null when the payload has no routable target

PASS src/firebase/pushNotificationPayload.test.ts
  normalizePushNotificationPayload
    ✓ normalizes notification and data payload fields (1 ms)
    ✓ falls back to data fields and message id

PASS src/services/notificationPreferenceService.test.ts
  notificationPreferenceService
    ✓ defaults push notifications to enabled
    ✓ persists disabled push notifications
    ✓ notifies subscribers when the preference changes (1 ms)

PASS src/services/deviceInstallation.test.ts
  deviceInstallation
    ✓ creates and persists an installation id when none exists (1 ms)
    ✓ returns the stored installation id without replacing it (1 ms)

PASS src/viewmodels/home/useHomeViewModel.auth.test.tsx
  useHomeViewModel auth behavior
    ✓ shows auth error and skips event loading when token is missing (311 ms)

PASS src/components/events/EventCard.test.tsx
  EventCard
    ✓ renders an event summary without crashing (25 ms)

PASS src/utils/eventCategoryPresentation.test.ts
  getEventCategoryPresentation
    ✓ keeps outdoors and volunteering visually distinct (1 ms)
    ✓ normalizes category names with punctuation
    ✓ returns readable foreground text for bright dark-theme colors

PASS src/services/ticketService.test.ts
  ticketService
    ✓ should be true

PASS src/components/events/EventCategoryChip.test.tsx
  EventCategoryChip
    ✓ renders the shared category emoji and color presentation (3 ms)

PASS src/components/profile/ProfileEventCard.test.tsx
  ProfileEventCard
    ✓ uses the shared category color and emoji presentation (5 ms)

PASS src/viewmodels/ticket/useEventActionsViewModel.test.tsx
  useEventActionsViewModel
    ✓ retries ticket lookup for joined public events and eventually exposes View Ticket (2060 ms)
    ✓ does not apply the new retry loop to protected events (56 ms)

PASS src/viewmodels/home/useHomeViewModel.test.tsx (25.028 s)
  useHomeViewModel
    ✓ loads initial categories and events on mount (488 ms)
    ✓ uses a reverse-geocoded label when searching the visible map area (673 ms)
    ✓ prefers the live location over the profile default when both are available (377 ms)
    ✓ uses the profile default location when live location is unavailable (363 ms)
    ✓ keeps showing the resolved default location after silent refresh (366 ms)
    ✓ requests the live location when no profile default exists and uses it when available (365 ms)
    ✓ loads favorite location options alphabetically and limits them to three items (55 ms)
    ✓ updates search text (3 ms)
    ✓ toggles selected category ids (6 ms)
    ✓ clears selected category ids (4 ms)
    ✓ refreshes events from the first page (365 ms)
    ✓ loads more events and appends them (374 ms)
    ✓ sets apiError when loading events fails (361 ms)
    ✓ sets apiError when loading categories fails (54 ms)
    discovery filters
      ✓ opens and closes filter modal (377 ms)
      ✓ does not apply draft filters until apply is pressed (331 ms)
      ✓ uses START_TIME as the default sort order (360 ms)
      ✓ applies DISTANCE sorting to the discovery request (671 ms)
      ✓ applies privacy and radius filters to discovery request (677 ms)
      ✓ applies category filters from modal to discovery request (677 ms)
      ✓ keeps selected chip categories together with modal categories (944 ms)
      ✓ clears chip category filters from the discovery request (944 ms)
      ✓ applies valid date range filters (685 ms)
      ✓ shows error for invalid from date and does not apply filters (321 ms)
      ✓ shows error for invalid to date and does not apply filters (371 ms)
      ✓ shows error when from date is in the past (371 ms)
      ✓ shows error when to date is earlier than from date (319 ms)
      ✓ resets draft filters and keeps modal open on reset (371 ms)
      ✓ clears filter error after user updates a date field (320 ms)
      ✓ keeps the applied sort order during load more and silent refresh (628 ms)
    location picker
      ✓ opens and closes location modal (315 ms)
      ✓ does not apply selected location immediately after choosing a suggestion (364 ms)
      ✓ applies selected location only after choose location is pressed (624 ms)
      ✓ resets location draft and keeps location modal open (366 ms)
      ✓ applies the hardcoded fallback location only after the user explicitly selects it (369 ms)
      ✓ applies a saved favorite location after it is selected (626 ms)
      ✓ keeps the applied custom location after the hook remounts (733 ms)
      ✓ keeps the applied custom location during silent refresh (368 ms)
      ✓ returns to the user profile default location after resetting a temporary location (368 ms)
    IN_PROGRESS event filtering
      ✓ excludes IN_PROGRESS events from the initial load (361 ms)
      ✓ excludes IN_PROGRESS events when loading more (366 ms)
      ✓ keeps events without a status field (316 ms)

Test Suites: 71 passed, 71 total
Tests:       681 passed, 681 total
Snapshots:   0 total
Time:        26.228 s
Ran all test suites.

  1. End-to-End (E2E) Tests (Maestro) These tests validate complete user journeys on an Android emulator, ensuring that the frontend, backend, and database work together correctly.
Scenario: completed event feedback rating
----------------------------------------
Running on emulator-5554
 > Flow completed-event-feedback-rating-test
Launch app "com.bounswe2026group11.socialeventmapper" with clear state... COMPLETED
Run login-flow.yaml...
  Run dev-build-bootstrap.yaml...
    Tap on (Optional) "http://10.0.2.2:8081"... COMPLETED
    Tap on point (90%,74%)... COMPLETED
    Tap on (Optional) "Continue"... WARNED
  Run dev-build-bootstrap.yaml... COMPLETED
  Assert that id: login-username-input is visible... COMPLETED
  Assert that id: login-password-input is visible... COMPLETED
  Assert that id: login-submit-button is visible... COMPLETED
  Tap on id: login-username-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_USERNAME}... COMPLETED
  Tap on id: login-password-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_PASSWORD}... COMPLETED
  Hide Keyboard... COMPLETED
  Tap on id: login-submit-button... COMPLETED
Run login-flow.yaml... COMPLETED
Tap on (Optional) "Don't allow"... WARNED


 Warning: Element not found: Text matching regex: Don't allow
Assert that id: tab-events is visible... COMPLETED
Tap on id: tab-events... COMPLETED
Assert that id: my-events-tab-completed is visible... COMPLETED
Tap on id: my-events-tab-completed... COMPLETED
Scrolling DOWN until id: my-event-card-${E2E_EVENT_TITLE} is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on id: my-event-card-${E2E_EVENT_TITLE}... COMPLETED
Scrolling DOWN until id: event-actions-view-full-event-button is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on id: event-actions-view-full-event-button... COMPLETED
Scrolling DOWN until id: discussion-qa-tab is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on id: discussion-qa-tab... COMPLETED
Scrolling UP until id: event-feedback-edit-button is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on id: event-feedback-edit-button... COMPLETED
Tap on id: event-feedback-star-3... COMPLETED
Tap on id: event-feedback-submit-button... COMPLETED
Assert that id: event-feedback-edit-button is visible... COMPLETED
Assert that id: event-feedback-edit-button is visible... COMPLETED


Scenario: edit event title
----------------------------------------
Running on emulator-5554
 > Flow edit-event-title-test
Launch app "com.bounswe2026group11.socialeventmapper" with clear state... COMPLETED
Run login-flow.yaml...
  Run dev-build-bootstrap.yaml...
    Tap on (Optional) "http://10.0.2.2:8081"... COMPLETED
    Tap on point (90%,74%)... COMPLETED
    Tap on (Optional) "Continue"... WARNED
  Run dev-build-bootstrap.yaml... COMPLETED
  Assert that id: login-username-input is visible... COMPLETED
  Assert that id: login-password-input is visible... COMPLETED
  Assert that id: login-submit-button is visible... COMPLETED
  Tap on id: login-username-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_USERNAME}... COMPLETED
  Tap on id: login-password-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_PASSWORD}... COMPLETED
  Hide Keyboard... COMPLETED
  Tap on id: login-submit-button... COMPLETED
Run login-flow.yaml... COMPLETED
Tap on (Optional) "Don't allow"... WARNED


 Warning: Element not found: Text matching regex: Don't allow
Assert that id: tab-events is visible... COMPLETED
Tap on id: tab-events... COMPLETED
Assert that id: my-events-tab-active is visible... COMPLETED
Tap on id: my-events-tab-active... COMPLETED
Scrolling DOWN until id: my-event-card-${E2E_ORIGINAL_EVENT_TITLE} is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on id: my-event-card-${E2E_ORIGINAL_EVENT_TITLE}... COMPLETED
Assert that "Edit Event" is visible... COMPLETED
Tap on "Edit Event"... COMPLETED
Assert that id: edit-event-title-input is visible... COMPLETED
Tap on id: edit-event-title-input... COMPLETED
Erase text... COMPLETED
Input text ${E2E_UPDATED_EVENT_TITLE}... COMPLETED
Hide Keyboard... COMPLETED
Scrolling DOWN until id: edit-event-save-button is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on id: edit-event-save-button... COMPLETED
Assert that id: edit-event-confirmation is visible... COMPLETED
Tap on id: edit-event-save-anyway-button... COMPLETED
Assert that "${E2E_UPDATED_EVENT_TITLE}" is visible... COMPLETED


Scenario: favorite event discussion post
----------------------------------------
Running on emulator-5554
 > Flow favorite-event-discussion-post-test
Launch app "com.bounswe2026group11.socialeventmapper" with clear state... COMPLETED
Run login-flow.yaml...
  Run dev-build-bootstrap.yaml...
    Tap on (Optional) "http://10.0.2.2:8081"... COMPLETED
    Tap on point (90%,74%)... COMPLETED
    Tap on (Optional) "Continue"... WARNED
  Run dev-build-bootstrap.yaml... COMPLETED
  Assert that id: login-username-input is visible... COMPLETED
  Assert that id: login-password-input is visible... COMPLETED
  Assert that id: login-submit-button is visible... COMPLETED
  Tap on id: login-username-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_USERNAME}... COMPLETED
  Tap on id: login-password-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_PASSWORD}... COMPLETED
  Hide Keyboard... COMPLETED
  Tap on id: login-submit-button... COMPLETED
Run login-flow.yaml... COMPLETED
Tap on (Optional) "Don't allow"... WARNED


 Warning: Element not found: Text matching regex: Don't allow
Assert that id: tab-favorites is visible... COMPLETED
Tap on id: tab-favorites... COMPLETED
Assert that "${E2E_EVENT_TITLE}" is visible... COMPLETED
Tap on id: profile-event-card-${E2E_EVENT_TITLE}... COMPLETED
Scrolling DOWN until id: discussion-question-input is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on id: discussion-question-input... COMPLETED
Input text ${E2E_DISCUSSION_MESSAGE}... COMPLETED
Hide Keyboard... COMPLETED
Scrolling DOWN until id: discussion-post-button is visible with speed 40, visibility percentage 100%, timeout 15000 ms, with centering disabled... COMPLETED
Tap on id: discussion-post-button... COMPLETED
Assert that "${E2E_DISCUSSION_MESSAGE}" is visible... COMPLETED


Scenario: favorite location save and apply
----------------------------------------
Running on emulator-5554
 > Flow favorite-location-save-and-apply-test
Launch app "com.bounswe2026group11.socialeventmapper" with clear state... COMPLETED
Run login-flow.yaml...
  Run dev-build-bootstrap.yaml...
    Tap on (Optional) "http://10.0.2.2:8081"... COMPLETED
    Tap on point (90%,74%)... COMPLETED
    Tap on (Optional) "Continue"... WARNED
  Run dev-build-bootstrap.yaml... COMPLETED
  Assert that id: login-username-input is visible... COMPLETED
  Assert that id: login-password-input is visible... COMPLETED
  Assert that id: login-submit-button is visible... COMPLETED
  Tap on id: login-username-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_USERNAME}... COMPLETED
  Tap on id: login-password-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_PASSWORD}... COMPLETED
  Hide Keyboard... COMPLETED
  Tap on id: login-submit-button... COMPLETED
Run login-flow.yaml... COMPLETED
Tap on (Optional) "Don't allow"... WARNED


 Warning: Element not found: Text matching regex: Don't allow
Assert that id: tab-favorites is visible... COMPLETED
Tap on id: tab-favorites... COMPLETED
Assert that id: favorites-tab-locations is visible... COMPLETED
Tap on id: favorites-tab-locations... COMPLETED
Assert that id: favorite-location-add-button is visible... COMPLETED
Tap on id: favorite-location-add-button... COMPLETED
Assert that id: favorite-location-name-input is visible... COMPLETED
Tap on id: favorite-location-name-input... COMPLETED
Input text ${E2E_LOCATION_NAME}... COMPLETED
Tap on id: favorite-location-address-input... COMPLETED
Input text ${E2E_LOCATION_QUERY}... COMPLETED
Hide Keyboard... COMPLETED
Assert that id: favorite-location-suggestion-0 is visible... COMPLETED
Tap on id: favorite-location-suggestion-0... COMPLETED
Tap on id: favorite-location-save-button... COMPLETED
Assert that id: favorite-location-name-${E2E_LOCATION_NAME} is visible... COMPLETED
Tap on id: tab-home... COMPLETED
Assert that id: home-location-picker-button is visible... COMPLETED
Tap on id: home-location-picker-button... COMPLETED
Assert that id: home-location-favorite-option-${E2E_LOCATION_NAME} is visible... COMPLETED
Tap on id: home-location-favorite-option-${E2E_LOCATION_NAME}... COMPLETED
Tap on id: home-location-apply-button... COMPLETED
Assert that id: home-location-apply-button is not visible... COMPLETED


Scenario: host approve join request
----------------------------------------
Running on emulator-5554
 > Flow host-approve-join-request-test
Launch app "com.bounswe2026group11.socialeventmapper" with clear state... COMPLETED
Run login-flow.yaml...
  Run dev-build-bootstrap.yaml...
    Tap on (Optional) "http://10.0.2.2:8081"... COMPLETED
    Tap on point (90%,74%)... COMPLETED
    Tap on (Optional) "Continue"... WARNED
  Run dev-build-bootstrap.yaml... COMPLETED
  Assert that id: login-username-input is visible... COMPLETED
  Assert that id: login-password-input is visible... COMPLETED
  Assert that id: login-submit-button is visible... COMPLETED
  Tap on id: login-username-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_USERNAME}... COMPLETED
  Tap on id: login-password-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_PASSWORD}... COMPLETED
  Hide Keyboard... COMPLETED
  Tap on id: login-submit-button... COMPLETED
Run login-flow.yaml... COMPLETED
Tap on (Optional) "Don't allow"... WARNED


 Warning: Element not found: Text matching regex: Don't allow
Assert that id: tab-events is visible... COMPLETED
Tap on id: tab-events... COMPLETED
Assert that id: my-events-tab-active is visible... COMPLETED
Tap on id: my-events-tab-active... COMPLETED
Scrolling DOWN until id: my-event-card-${E2E_EVENT_TITLE} is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on id: my-event-card-${E2E_EVENT_TITLE}... COMPLETED
Scrolling DOWN until "View Full Event" is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on "View Full Event"... COMPLETED
Scrolling DOWN until id: pending-requests-button is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on id: pending-requests-button... COMPLETED
Assert that id: join-request-row-${E2E_REQUEST_USERNAME} is visible... COMPLETED
Tap on id: join-request-approve-${E2E_REQUEST_USERNAME}... COMPLETED
Assert that id: join-request-row-${E2E_REQUEST_USERNAME} is not visible... COMPLETED


Scenario: invitation accept
----------------------------------------
Running on emulator-5554
 > Flow invitation-accept-test
Launch app "com.bounswe2026group11.socialeventmapper" with clear state... COMPLETED
Run login-flow.yaml...
  Run dev-build-bootstrap.yaml...
    Tap on (Optional) "http://10.0.2.2:8081"... COMPLETED
    Tap on point (90%,74%)... COMPLETED
    Tap on (Optional) "Continue"... WARNED
  Run dev-build-bootstrap.yaml... COMPLETED
  Assert that id: login-username-input is visible... COMPLETED
  Assert that id: login-password-input is visible... COMPLETED
  Assert that id: login-submit-button is visible... COMPLETED
  Tap on id: login-username-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_USERNAME}... COMPLETED
  Tap on id: login-password-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_PASSWORD}... COMPLETED
  Hide Keyboard... COMPLETED
  Tap on id: login-submit-button... COMPLETED
Run login-flow.yaml... COMPLETED
Tap on (Optional) "Don't allow"... WARNED


 Warning: Element not found: Text matching regex: Don't allow
Assert that id: tab-profile is visible... COMPLETED
Tap on id: tab-profile... COMPLETED
Assert that "${E2E_INVITATION_EVENT_TITLE}" is visible... COMPLETED
Tap on "${E2E_INVITATION_EVENT_TITLE}"... COMPLETED
Assert that id: invited-status-chip is visible... COMPLETED
Assert that id: accept-invitation-button is visible... COMPLETED
Tap on id: accept-invitation-button... COMPLETED
Assert that id: joined-status-chip is visible... COMPLETED


Scenario: my events view ticket
----------------------------------------
Running on emulator-5554
 > Flow my-events-view-ticket-test
Launch app "com.bounswe2026group11.socialeventmapper" with clear state... COMPLETED
Run login-flow.yaml...
  Run dev-build-bootstrap.yaml...
    Tap on (Optional) "http://10.0.2.2:8081"... COMPLETED
    Tap on point (90%,74%)... COMPLETED
    Tap on (Optional) "Continue"... WARNED
  Run dev-build-bootstrap.yaml... COMPLETED
  Assert that id: login-username-input is visible... COMPLETED
  Assert that id: login-password-input is visible... COMPLETED
  Assert that id: login-submit-button is visible... COMPLETED
  Tap on id: login-username-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_USERNAME}... COMPLETED
  Tap on id: login-password-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_PASSWORD}... COMPLETED
  Hide Keyboard... COMPLETED
  Tap on id: login-submit-button... COMPLETED
Run login-flow.yaml... COMPLETED
Tap on (Optional) "Don't allow"... WARNED


 Warning: Element not found: Text matching regex: Don't allow
Assert that id: tab-events is visible... COMPLETED
Tap on id: tab-events... COMPLETED
Assert that id: my-events-tab-active is visible... COMPLETED
Tap on id: my-events-tab-active... COMPLETED
Scrolling DOWN until id: my-event-card-${E2E_EVENT_TITLE} is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Tap on id: my-event-card-${E2E_EVENT_TITLE}... COMPLETED
Assert that id: event-actions-primary-button is visible... COMPLETED
Tap on id: event-actions-primary-button... COMPLETED
Assert that "Ticket" is visible... COMPLETED
Assert that "${E2E_EVENT_TITLE}" is visible... COMPLETED
Scrolling DOWN until "Refresh Code" is visible with speed 40, visibility percentage 100%, timeout 30000 ms, with centering disabled... COMPLETED
Assert that "Refresh Code" is visible... COMPLETED


Scenario: protected event join request
----------------------------------------
Running on emulator-5554
 > Flow protected-event-join-request-test
Launch app "com.bounswe2026group11.socialeventmapper" with clear state... COMPLETED
Run login-flow.yaml...
  Run dev-build-bootstrap.yaml...
    Tap on (Optional) "http://10.0.2.2:8081"... COMPLETED
    Tap on point (90%,74%)... COMPLETED
    Tap on (Optional) "Continue"... WARNED
  Run dev-build-bootstrap.yaml... COMPLETED
  Assert that id: login-username-input is visible... COMPLETED
  Assert that id: login-password-input is visible... COMPLETED
  Assert that id: login-submit-button is visible... COMPLETED
  Tap on id: login-username-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_USERNAME}... COMPLETED
  Tap on id: login-password-input... COMPLETED
  Erase text... COMPLETED
  Input text ${E2E_PASSWORD}... COMPLETED
  Hide Keyboard... COMPLETED
  Tap on id: login-submit-button... COMPLETED
Run login-flow.yaml... COMPLETED
Tap on (Optional) "Don't allow"... WARNED


 Warning: Element not found: Text matching regex: Don't allow
Assert that id: toggle-list is visible... COMPLETED
Tap on id: toggle-list... COMPLETED
Assert that id: home-search-input is visible... COMPLETED
Tap on id: home-search-input... COMPLETED
Erase text... COMPLETED
Input text ${E2E_SEARCH_QUERY}... COMPLETED
Hide Keyboard... COMPLETED
Assert that "${E2E_EVENT_TITLE}" is visible... COMPLETED
Tap on "${E2E_EVENT_TITLE}"... COMPLETED
Assert that id: request-to-join-button is visible... COMPLETED
Tap on id: request-to-join-button... COMPLETED
Assert that id: join-request-message-input is visible... COMPLETED
Tap on id: join-request-message-input... COMPLETED
Input text ${E2E_JOIN_MESSAGE}... COMPLETED
Hide Keyboard... COMPLETED
Tap on id: join-request-send-button... COMPLETED
Assert that id: join-request-pending-chip is visible... COMPLETED



👥 Team Members

Labs

Meetings

Milestones

Requirements & Analysis

Scenarios

Use Case Diagrams

Class Diagrams

Sequence Diagrams

Planning

Testing

MVP Demo Plan

Clone this wiki locally