Test Coverage Specification
Source of truth for what must be tested on forsyt.io.
Update the Status Tracker (below) after every implementation.
Reference docs/INTERACTION_PATTERNS.md for code patterns for each scenario type.
Status Tracker
Quick summary: 3 passing · 3 skeleton (placeholder selectors) · 28+ not started
Update this after every test implementation. Do not leave stale statuses.
| Test ID | Status |
|---|
test_homepage_opens | ✅ Done |
test_homepage_mobile_viewport | ✅ Done |
test_homepage_desktop_viewport | ✅ Done |
test_login_page_loads | 🟡 Skeleton — placeholder selectors |
test_login_with_valid_credentials | 🟡 Skeleton — placeholder selectors |
test_login_invalid_credentials_shows_error | 🟡 Skeleton — placeholder selectors |
test_splash_page_loads | ⬜ Not started |
test_splash_logo_visible | ⬜ Not started |
test_splash_transitions_to_app | ⬜ Not started |
test_sports_feed_loads | ⬜ Not started |
test_sports_feed_heading_visible | ⬜ Not started |
test_bottom_nav_visible | ⬜ Not started |
test_bottom_nav_sports_tab_tap | ⬜ Not started |
test_bottom_nav_live_tab_tap | ⬜ Not started |
test_bottom_nav_mybets_tab_tap | ⬜ Not started |
test_sport_filter_tabs_visible | ⬜ Not started |
test_sport_filter_changes_content | ⬜ Not started |
test_event_cards_visible | ⬜ Not started |
test_live_page_loads | ⬜ Not started |
test_live_events_list_visible | ⬜ Not started |
test_my_bets_page_loads | ⬜ Not started |
test_my_bets_redirects_unauthenticated | ⬜ Not started |
test_account_page_loads | ⬜ Not started |
test_logout_works | ⬜ Not started |
test_event_detail_page_loads | ⬜ Not started |
test_404_page_renders | ⬜ Not started |
test_no_console_errors_on_home | ⬜ Not started |
test_no_horizontal_overflow_home | ⬜ Not started |
test_touch_targets_bottom_nav | ⬜ Not started |
Legend: ✅ Done · 🟡 Skeleton (placeholder selectors) · 🔴 Failing · ⬜ Not started · 🚫 Removed
Coverage Tiers
| Tier | Marker | Runs when | Goal | Max time |
|---|
| Smoke | @pytest.mark.smoke | Every commit, every deploy | App is alive | < 2 min total |
| Regression | @pytest.mark.regression | Nightly, pre-release | Nothing is broken | < 15 min total |
| Visual | @pytest.mark.visual | Weekly, post Figma change | UI matches design | On-demand |
| AI | @pytest.mark.ai | On-demand | AI pipeline works | On-demand |
Device Matrix
Every smoke and regression test must pass on both:
| Key | Viewport | Emulation |
|---|
mobile (default) | 402×874 | is_mobile=true, touch |
desktop | 1280×720 | is_mobile=false, no touch |
Additional devices for extended regression:
| Key | Viewport | Notes |
|---|
iphone_14_pro | 393×852 | Safari engine → use BROWSER=webkit |
pixel_7 | 412×915 | Chrome on Android |
tablet | 768×1024 | Mid-size layout |
Page Coverage
1. Splash Screen
URL: /
Figma: Node 837:22442 — 402×874 mobile frame
Description: First screen users see. White logo centred on background. Status bar at top. Bottom nav hidden.
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_splash_page_loads | Page navigates without error | smoke | mobile+desktop | Page load |
test_splash_logo_visible | Forsyt.io logo is rendered and visible | smoke | mobile+desktop | Element visibility |
test_splash_status_bar_present | iPhone-style status bar is present at the top | regression | mobile | Element visibility |
test_splash_bottom_nav_hidden | Bottom navigation is not visible on the splash | regression | mobile | Element visibility |
test_splash_transitions_to_app | Splash auto-transitions or has a CTA to enter the app | smoke | mobile | Navigation flow |
test_splash_no_console_errors | No JS errors during splash screen load | regression | mobile+desktop | Console errors |
test_splash_no_horizontal_overflow | No content wider than the viewport | regression | mobile | Scroll/overflow |
2. Home / Sports Feed
URL: / or /sports (post-splash)
Description: Main content page. Sport filter tabs at top. Event cards in a scrollable list. Bottom nav visible.
2a. Page & Layout
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_sports_feed_loads | Sports feed renders without error | smoke | mobile+desktop | Page load |
test_sports_feed_heading_visible | Page heading is visible | smoke | mobile+desktop | Element visibility |
test_sports_no_horizontal_overflow | No horizontal scrollbar on mobile | regression | mobile | Scroll/overflow |
test_sports_no_console_errors | No JS errors on sports feed | regression | mobile+desktop | Console errors |
2b. Bottom Navigation (mobile)
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_bottom_nav_visible | Bottom nav bar is rendered | smoke | mobile | Element visibility |
test_bottom_nav_sports_tab_exists | Sports tab icon+label is visible | smoke | mobile | Element visibility |
test_bottom_nav_live_tab_exists | Live tab icon+label is visible | smoke | mobile | Element visibility |
test_bottom_nav_mybets_tab_exists | My Bets tab icon+label is visible | smoke | mobile | Element visibility |
test_bottom_nav_badge_visible | Notification badge renders when count > 0 | regression | mobile | Element visibility |
test_bottom_nav_badge_count_is_numeric | Badge shows a number, not empty text | regression | mobile | Data validation |
test_bottom_nav_sports_tab_tap | Tapping Sports tab navigates to sports | smoke | mobile | Tab navigation |
test_bottom_nav_live_tab_tap | Tapping Live tab navigates to live page | smoke | mobile | Tab navigation |
test_bottom_nav_mybets_tab_tap | Tapping My Bets tab navigates to my-bets | smoke | mobile | Tab navigation |
test_bottom_nav_tab_touch_target | Each tab is at least 44×44px | regression | mobile | Touch target |
test_bottom_nav_active_tab_indicates_current | Active tab is visually highlighted | regression | mobile | Data change |
2c. Sport Filter Tabs
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_sport_filter_tabs_visible | Filter tabs (Football, Basketball, etc.) are rendered | smoke | mobile+desktop | Element visibility |
test_sport_filter_tabs_swipeable | Tab bar can be swiped horizontally on mobile | regression | mobile | Swipe |
test_sport_filter_changes_content | Tapping a sport tab updates the event list | regression | mobile+desktop | Data change |
test_sport_filter_active_state_updates | Active tab indicator moves to the tapped tab | regression | mobile | Data change |
2d. Event Cards
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_event_cards_visible | At least one event card is rendered | smoke | mobile+desktop | Element count |
test_event_card_shows_team_names | Each card shows team / participant names | regression | mobile+desktop | Data validation |
test_event_card_shows_odds | Each card shows at least 2 odds values | regression | mobile+desktop | Data validation |
test_event_card_shows_time_or_status | Each card shows match time or status | regression | mobile | Data validation |
test_event_card_is_tappable | Tapping an event card opens event detail | regression | mobile | Button tap |
test_scroll_loads_more_events | Scrolling down loads more events (infinite scroll) | regression | mobile | Vertical scroll |
3. Live / In-Play
URL: /live
Description: Real-time events page. Shows in-progress matches with live scores and odds.
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_live_page_loads | Live page renders | smoke | mobile+desktop | Page load |
test_live_heading_visible | "Live" heading or indicator is visible | smoke | mobile+desktop | Element visibility |
test_live_events_list_visible | Event cards are shown | smoke | mobile+desktop | Element count |
test_live_score_displayed | Live scores are rendered on event cards | regression | mobile | Data validation |
test_live_filter_by_sport | Sport filter changes the live event list | regression | mobile+desktop | Data change |
test_live_score_not_empty_after_wait | Score values are still present after 5s | regression | mobile | Data validation |
test_live_no_console_errors | No JS errors on the live page | regression | mobile+desktop | Console errors |
4. Login / Authentication
URL: /login
4a. Page Elements
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_login_page_loads | Login page renders | smoke | mobile+desktop | Page load |
test_login_email_field_visible | Email input field is visible | smoke | mobile+desktop | Element visibility |
test_login_password_field_visible | Password input field is visible | smoke | mobile+desktop | Element visibility |
test_login_submit_button_visible | Submit / Sign In button is visible | smoke | mobile+desktop | Element visibility |
test_login_submit_button_tappable | Submit button responds to tap | regression | mobile | Button tap |
test_login_submit_button_touch_target | Submit button is at least 44×44px | regression | mobile | Touch target |
test_login_forgot_password_link_visible | Forgot password link is present | regression | mobile+desktop | Element visibility |
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_login_accepts_email_input | Email field accepts text input | regression | mobile+desktop | Form fill |
test_login_accepts_password_input | Password field accepts text input | regression | mobile+desktop | Form fill |
test_login_password_masked | Password input is of type password (masked) | regression | mobile+desktop | Form fill |
test_login_empty_form_shows_validation | Submitting empty form shows validation | regression | mobile+desktop | Form validation |
test_login_invalid_email_shows_error | Invalid email format triggers error | regression | mobile | Form validation |
test_login_invalid_credentials_shows_error | Wrong credentials shows error banner | regression | mobile+desktop | Error state |
test_login_error_message_has_text | Error message element is not empty | regression | mobile+desktop | Data validation |
4c. Authentication Flow
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_login_with_valid_credentials | Valid login lands on the expected page | smoke | mobile+desktop | Navigation flow |
test_login_persists_session | Reloading after login keeps the user authenticated | regression | mobile | Data change |
5. My Bets / Bet Slip
URL: /my-bets
Requires: Authenticated session — use authenticated_page
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_my_bets_page_loads | Page renders for authenticated users | smoke | mobile+desktop | Page load |
test_my_bets_redirects_unauthenticated | Unauthenticated users go to login | smoke | mobile+desktop | Navigation flow |
test_active_bets_section_visible | Active bets section is rendered | regression | mobile | Element visibility |
test_settled_bets_tab_visible | Settled / History tab is present | regression | mobile | Element visibility |
test_settled_bets_tab_loads_content | Tapping Settled tab shows past bets | regression | mobile | Tab navigation |
test_bet_card_is_visible | At least one bet card is rendered | regression | mobile | Element count |
test_bet_card_shows_event_name | Bet card shows the event / match name | regression | mobile | Data validation |
test_bet_card_shows_stake | Bet card shows the stake amount | regression | mobile | Data validation |
test_bet_card_expands_on_tap | Tapping a bet card expands details | regression | mobile | Button tap |
test_my_bets_no_console_errors | No JS errors on My Bets | regression | mobile | Console errors |
6. Account / Profile
URL: /account
Requires: Authenticated session
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_account_page_loads | Account page renders | smoke | mobile+desktop | Page load |
test_account_shows_username | Logged-in username / email is displayed | regression | mobile+desktop | Data validation |
test_account_shows_avatar_or_initials | User avatar or initials renders | regression | mobile | Element visibility |
test_logout_button_visible | Logout button is present | regression | mobile+desktop | Element visibility |
test_logout_works | Tapping logout redirects to login | regression | mobile+desktop | Navigation flow |
7. Event Detail
URL: /event/<id> or similar
Description: Individual match/event page with odds, teams, betting options.
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_event_detail_page_loads | Event detail renders after tapping an event card | smoke | mobile+desktop | Page load |
test_event_teams_visible | Home and away team names are shown | smoke | mobile+desktop | Element visibility |
test_event_odds_visible | Betting odds are displayed | smoke | mobile+desktop | Element visibility |
test_event_odds_are_numeric | Odds values are non-empty numbers | regression | mobile+desktop | Data validation |
test_event_back_navigation | Back button / back gesture returns to feed | regression | mobile | Back navigation |
test_event_odds_tappable | Tapping an odds button selects it (state changes) | regression | mobile | Button tap |
test_event_no_console_errors | No JS errors on event detail | regression | mobile | Console errors |
8. Error & Edge Cases
| Test ID | Scenario | Tier | Device | Pattern |
|---|
test_404_page_renders | /nonexistent URL shows a 404 or error page | regression | mobile+desktop | Error state |
test_network_error_shows_error_state | Sports feed shows error state when API fails | regression | mobile | Error state (route abort) |
test_no_console_errors_on_home | No uncaught JS errors on homepage | regression | mobile+desktop | Console errors |
Accessibility Coverage (from Figma)
Based on the forsyt.io Figma design (mobile-first, 402×874 canvas):
| Test ID | Scenario | Tier | Device |
|---|
test_touch_targets_bottom_nav | All bottom nav tabs ≥ 44×44px | regression | mobile |
test_touch_targets_login_form | Login button and inputs ≥ 44×44px | regression | mobile |
test_touch_targets_event_cards | Event cards large enough to tap without mis-tap | regression | mobile |
test_no_horizontal_overflow_home | No horizontal scrollbar on home | regression | mobile |
test_no_horizontal_overflow_sports | No horizontal scrollbar on sports page | regression | mobile |
test_text_readable_minimum_size | No text smaller than 12px on mobile | regression | mobile |
test_status_bar_not_overlapping_content | Content does not sit behind the status bar | regression | mobile |
Visual Coverage (Figma Comparison)
| Test ID | Figma Node | Page | Device |
|---|
test_visual_splash_screen | 837:22442 | Splash | mobile |
test_visual_sports_feed | TBD | Sports | mobile |
test_visual_bottom_nav | TBD | Sports (authenticated) | mobile |
test_visual_login_form | TBD | Login | mobile + desktop |
test_visual_event_card | TBD | Sports | mobile |
Coverage Targets
| Tier | Target pass rate | Max duration |
|---|
| Smoke — mobile | 100% | < 2 min |
| Smoke — desktop | 100% | < 2 min |
| Regression — mobile | 95%+ | < 15 min |
| Regression — desktop | 95%+ | < 15 min |