""" Step 5 — Session Management Tests - test_session_list_empty: Shows empty state when no sessions exist - test_create_session_minimal: Create session with only required field (title) - test_create_session_full: Create session with all fields including items - test_session_appears_in_list: Created session appears in the list - test_session_detail_view: Detail view shows all session data - test_edit_session: Edit a session and verify changes - test_delete_session: Delete a session with confirmation - test_delete_session_cancel: Cancelling delete does not remove session - test_search_sessions: Search filters sessions by title - test_search_no_results: Search with no matches shows empty message - test_search_clear_button: Clear button empties the search field and restores the full list - test_validation_title_required: Empty title shows validation error - test_duplicate_title_rejected: Creating session with duplicate title shows error - test_reorder_items: Reorder items in session - test_remove_item: Remove an item from session - test_action_bar_buttons: New and Search buttons appear in action bar - test_create_session_with_exercise_and_combo: Create session mixing exercises and combos - test_create_session_with_reps_and_weight: Create session with reps/weight values - test_edit_session_reps_and_weight: Edit session and change reps/weight values - test_reps_weight_defaults: Reps default to 1 and weight defaults to 0 """ from playwright.sync_api import Page, expect def _wait_for_db(page: Page, app_url: str): """Navigate and wait for the database to be ready.""" page.goto(app_url) page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) def _go_to_sessions(page: Page, app_url: str): """Navigate to the sessions list and wait for it to load.""" _wait_for_db(page, app_url) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) def _clean_sessions(page: Page): """Remove all sessions via the repository.""" page.evaluate( """async () => { const sessions = await window.__repos.sessions.getAll(); for (const s of sessions) { await window.__repos.sessions.delete(s.id); } }""" ) def _clean_exercises(page: Page): """Remove all exercises via the repository.""" page.evaluate( """async () => { const exercises = await window.__repos.exercises.getAll(); for (const e of exercises) { await window.__repos.exercises.delete(e.id); } }""" ) def _clean_combos(page: Page): """Remove all combos via the repository.""" page.evaluate( """async () => { const combos = await window.__repos.combos.getAll(); for (const c of combos) { await window.__repos.combos.delete(c.id); } }""" ) def _create_exercise_via_repo(page: Page, title): """Create an exercise via the repository and return its ID.""" return page.evaluate( """async (title) => { const uuid = await window.__repos.settings.get('user_uuid'); return window.__repos.exercises.create({ title: title, description: '', asymmetric: false, alternate: false, image_urls: [], video_urls: [], default_reps: 10, default_weight: 0, created_by: uuid }); }""", title, ) def _create_combo_via_repo(page: Page, title): """Create a combo via the repository and return its ID.""" return page.evaluate( """async (title) => { const uuid = await window.__repos.settings.get('user_uuid'); return window.__repos.combos.create({ title: title, description: '', type: 'NONE', timer_config: {}, created_by: uuid }); }""", title, ) def test_session_list_empty(page: Page, app_url: str): """Empty state is shown when no sessions exist.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) expect(page.locator('[data-testid="session-empty"]')).to_be_visible() def test_create_session_minimal(page: Page, app_url: str): """Create a session with only the required title field.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "My First Session") page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) expect(page.locator('[data-testid="session-detail-title"]')).to_have_text("My First Session") _clean_sessions(page) def test_create_session_full(page: Page, app_url: str): """Create a session with all fields including items.""" _go_to_sessions(page, app_url) _clean_sessions(page) _clean_exercises(page) _clean_combos(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) # Create exercise and combo ex_id = _create_exercise_via_repo(page, "Push-ups") combo_id = _create_combo_via_repo(page, "Warm-up Combo") page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) # Create session page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Upper Body Day") page.fill('[data-testid="session-description"]', "Focus on chest and shoulders") # Add exercise page.select_option('[data-testid="session-item-type-select"]', "exercise") page.select_option('[data-testid="session-item-select"]', ex_id) page.click('[data-testid="session-item-add"]') # Add combo page.select_option('[data-testid="session-item-type-select"]', "combo") page.select_option('[data-testid="session-item-select"]', combo_id) page.click('[data-testid="session-item-add"]') page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) expect(page.locator('[data-testid="session-detail-title"]')).to_have_text("Upper Body Day") expect(page.locator('[data-testid="session-detail-description"]')).to_have_text( "Focus on chest and shoulders" ) expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("Push-ups") expect(page.locator('[data-testid="session-detail-item-1"]')).to_contain_text("Warm-up Combo") _clean_sessions(page) _clean_exercises(page) _clean_combos(page) def test_session_appears_in_list(page: Page, app_url: str): """Created session appears in the list view.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Test Session") page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) page.click('[data-testid="session-back-btn"]') page.wait_for_timeout(500) expect(page.locator('[data-testid="session-card-title"]')).to_have_text("Test Session") _clean_sessions(page) def test_session_detail_view(page: Page, app_url: str): """Detail view shows all session data correctly.""" _go_to_sessions(page, app_url) _clean_sessions(page) _clean_exercises(page) ex_id = _create_exercise_via_repo(page, "Burpees") # Create session via repo session_id = page.evaluate( """async ({ exId }) => { const uuid = await window.__repos.settings.get('user_uuid'); const id = await window.__repos.sessions.create({ title: 'HIIT Session', description: 'High intensity interval training', created_by: uuid }); await window.__repos.sessions.setItems(id, [ { item_id: exId, item_type: 'exercise', repetitions: 3, weight: 0.0 } ]); return id; }""", {"exId": ex_id}, ) page.goto(f"{app_url}/#/sessions/{session_id}") page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) expect(page.locator('[data-testid="session-detail-title"]')).to_have_text("HIIT Session") expect(page.locator('[data-testid="session-detail-description"]')).to_have_text( "High intensity interval training" ) expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("Burpees") _clean_sessions(page) _clean_exercises(page) def test_edit_session(page: Page, app_url: str): """Edit a session and verify changes are persisted.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Original Session") page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) page.click('[data-testid="session-edit-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Updated Session") page.fill('[data-testid="session-description"]', "Updated description") page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) expect(page.locator('[data-testid="session-detail-title"]')).to_have_text("Updated Session") expect(page.locator('[data-testid="session-detail-description"]')).to_have_text( "Updated description" ) _clean_sessions(page) def test_delete_session(page: Page, app_url: str): """Delete a session with confirmation dialog.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "To Delete") page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) page.on("dialog", lambda dialog: dialog.accept()) page.click('[data-testid="session-delete-btn"]') page.wait_for_timeout(500) expect(page.locator('[data-testid="session-empty"]')).to_be_visible() def test_delete_session_cancel(page: Page, app_url: str): """Cancelling the delete dialog does not remove the session.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Keep Me") page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) page.on("dialog", lambda dialog: dialog.dismiss()) page.click('[data-testid="session-delete-btn"]') page.wait_for_timeout(500) expect(page.locator('[data-testid="session-detail-title"]')).to_have_text("Keep Me") _clean_sessions(page) def test_search_sessions(page: Page, app_url: str): """Search filters sessions by title.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.evaluate( """async () => { const uuid = await window.__repos.settings.get('user_uuid'); await window.__repos.sessions.create({ title: 'Upper Body', description: '', created_by: uuid }); await window.__repos.sessions.create({ title: 'Lower Body', description: '', created_by: uuid }); await window.__repos.sessions.create({ title: 'Full Body', description: '', created_by: uuid }); }""" ) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) expect(page.locator('[data-testid="session-card-title"]')).to_have_count(3) page.click('[data-testid="session-search-toggle"]') page.wait_for_selector('[data-testid="session-search-input"]') page.fill('[data-testid="session-search-input"]', "Upper") page.wait_for_timeout(500) expect(page.locator('[data-testid="session-card-title"]')).to_have_count(1) expect(page.locator('[data-testid="session-card-title"]')).to_have_text("Upper Body") _clean_sessions(page) def test_search_no_results(page: Page, app_url: str): """Search with no matches shows no-results message.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.evaluate( """async () => { const uuid = await window.__repos.settings.get('user_uuid'); await window.__repos.sessions.create({ title: 'Upper Body', description: '', created_by: uuid }); }""" ) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-search-toggle"]') page.fill('[data-testid="session-search-input"]', "zzzznotfound") page.wait_for_timeout(500) expect(page.locator('[data-testid="session-no-results"]')).to_be_visible() _clean_sessions(page) def test_search_clear_button(page: Page, app_url: str): """Clear button empties the search field and restores the full list.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.evaluate( """async () => { const uuid = await window.__repos.settings.get('user_uuid'); await window.__repos.sessions.create({ title: 'Upper Body', description: '', created_by: uuid }); await window.__repos.sessions.create({ title: 'Lower Body', description: '', created_by: uuid }); }""" ) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-search-toggle"]') expect(page.locator('[data-testid="session-search-clear"]')).not_to_be_visible() page.fill('[data-testid="session-search-input"]', "Upper") page.wait_for_timeout(500) expect(page.locator('[data-testid="session-card-title"]')).to_have_count(1) page.click('[data-testid="session-search-clear"]') expect(page.locator('[data-testid="session-search-input"]')).to_have_value("") page.wait_for_timeout(500) expect(page.locator('[data-testid="session-card-title"]')).to_have_count(2) expect(page.locator('[data-testid="session-search-input"]')).to_be_focused() _clean_sessions(page) def test_validation_title_required(page: Page, app_url: str): """Empty title shows validation error and prevents save.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.click('[data-testid="session-save"]') expect(page.locator('[data-testid="session-title-error"]')).to_be_visible() expect(page.locator('[data-testid="session-title"]')).to_be_visible() def test_duplicate_title_rejected(page: Page, app_url: str): """Creating a session with a duplicate title shows an error.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Unique Session") page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) page.click('[data-testid="session-back-btn"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Unique Session") page.click('[data-testid="session-save"]') page.wait_for_timeout(500) title_error_visible = page.locator('[data-testid="session-title-error"]').is_visible() save_error_visible = page.locator('[data-testid="session-save-error"]').is_visible() assert title_error_visible or save_error_visible, "Expected duplicate title error" _clean_sessions(page) def test_reorder_items(page: Page, app_url: str): """Reorder items in a session.""" _go_to_sessions(page, app_url) _clean_sessions(page) _clean_exercises(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) ex1_id = _create_exercise_via_repo(page, "Push-ups") ex2_id = _create_exercise_via_repo(page, "Squats") ex3_id = _create_exercise_via_repo(page, "Burpees") page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) # Create session with 3 exercises page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Reorder Test") for ex_id in [ex1_id, ex2_id, ex3_id]: page.select_option('[data-testid="session-item-type-select"]', "exercise") page.select_option('[data-testid="session-item-select"]', ex_id) page.click('[data-testid="session-item-add"]') page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) # Go to edit page.click('[data-testid="session-edit-btn"]') page.wait_for_selector('[data-testid="session-title"]') # Move Squats (index 1) up page.click('[data-testid="session-item-move-up-1"]') # Save page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) # Verify order: Squats, Push-ups, Burpees expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("Squats") expect(page.locator('[data-testid="session-detail-item-1"]')).to_contain_text("Push-ups") expect(page.locator('[data-testid="session-detail-item-2"]')).to_contain_text("Burpees") _clean_sessions(page) _clean_exercises(page) def test_remove_item(page: Page, app_url: str): """Remove an item from a session.""" _go_to_sessions(page, app_url) _clean_sessions(page) _clean_exercises(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) ex1_id = _create_exercise_via_repo(page, "Push-ups") ex2_id = _create_exercise_via_repo(page, "Squats") page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) # Create session with 2 exercises page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Remove Test") for ex_id in [ex1_id, ex2_id]: page.select_option('[data-testid="session-item-type-select"]', "exercise") page.select_option('[data-testid="session-item-select"]', ex_id) page.click('[data-testid="session-item-add"]') page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) # Go to edit page.click('[data-testid="session-edit-btn"]') page.wait_for_selector('[data-testid="session-title"]') # Remove first item page.click('[data-testid="session-item-remove-0"]') page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) # Only Squats should remain expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("Squats") _clean_sessions(page) _clean_exercises(page) def test_action_bar_buttons(page: Page, app_url: str): """New and Search buttons are visible in the action bar on the session list.""" _go_to_sessions(page, app_url) _clean_sessions(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) expect(page.locator('[data-testid="session-new-btn"]')).to_be_visible() expect(page.locator('[data-testid="session-search-toggle"]')).to_be_visible() def test_create_session_with_exercise_and_combo(page: Page, app_url: str): """Create session mixing exercises and combos.""" _go_to_sessions(page, app_url) _clean_sessions(page) _clean_exercises(page) _clean_combos(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) ex_id = _create_exercise_via_repo(page, "Push-ups") combo_id = _create_combo_via_repo(page, "Warm-up") page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Mixed Session") # Add exercise page.select_option('[data-testid="session-item-type-select"]', "exercise") page.select_option('[data-testid="session-item-select"]', ex_id) page.click('[data-testid="session-item-add"]') # Add combo page.select_option('[data-testid="session-item-type-select"]', "combo") page.select_option('[data-testid="session-item-select"]', combo_id) page.click('[data-testid="session-item-add"]') page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("Push-ups") expect(page.locator('[data-testid="session-detail-item-1"]')).to_contain_text("Warm-up") _clean_sessions(page) _clean_exercises(page) _clean_combos(page) def test_create_session_with_reps_and_weight(page: Page, app_url: str): """Create session with exercises and set reps/weight values.""" _go_to_sessions(page, app_url) _clean_sessions(page) _clean_exercises(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) ex1_id = _create_exercise_via_repo(page, "Push-ups") ex2_id = _create_exercise_via_repo(page, "Squats") page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Reps Weight Test") # Add first exercise page.select_option('[data-testid="session-item-type-select"]', "exercise") page.select_option('[data-testid="session-item-select"]', ex1_id) page.click('[data-testid="session-item-add"]') # Add second exercise page.select_option('[data-testid="session-item-type-select"]', "exercise") page.select_option('[data-testid="session-item-select"]', ex2_id) page.click('[data-testid="session-item-add"]') # Set reps and weight for first exercise page.fill('[data-testid="session-item-reps-0"]', "12") page.fill('[data-testid="session-item-weight-0"]', "50") # Set reps for second exercise (weight stays default) page.fill('[data-testid="session-item-reps-1"]', "15") page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) # Verify detail view shows reps and weight expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("Push-ups") expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("12") expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("50") expect(page.locator('[data-testid="session-detail-item-1"]')).to_contain_text("Squats") expect(page.locator('[data-testid="session-detail-item-1"]')).to_contain_text("15") _clean_sessions(page) _clean_exercises(page) def test_edit_session_reps_and_weight(page: Page, app_url: str): """Edit session and change reps/weight values.""" _go_to_sessions(page, app_url) _clean_sessions(page) _clean_exercises(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) ex_id = _create_exercise_via_repo(page, "Deadlifts") # Create session page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Edit Reps Weight Test") page.select_option('[data-testid="session-item-type-select"]', "exercise") page.select_option('[data-testid="session-item-select"]', ex_id) page.click('[data-testid="session-item-add"]') page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) # Edit session page.click('[data-testid="session-edit-btn"]') page.wait_for_selector('[data-testid="session-title"]') # Change reps and weight page.fill('[data-testid="session-item-reps-0"]', "8") page.fill('[data-testid="session-item-weight-0"]', "100") page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) # Verify updated values expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("Deadlifts") expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("8") expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("100") _clean_sessions(page) _clean_exercises(page) def test_combo_item_no_weight_in_form(page: Page, app_url: str): """Combo items do not show weight input in session form.""" _go_to_sessions(page, app_url) _clean_sessions(page) _clean_exercises(page) _clean_combos(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) combo_id = _create_combo_via_repo(page, "Warm-up") page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Combo Weight Test") # Add combo page.select_option('[data-testid="session-item-type-select"]', "combo") page.select_option('[data-testid="session-item-select"]', combo_id) page.click('[data-testid="session-item-add"]') # Verify reps input exists but weight input does not expect(page.locator('[data-testid="session-item-reps-0"]')).to_be_visible() expect(page.locator('[data-testid="session-item-weight-0"]')).not_to_be_attached() # Save and verify detail view shows 0 for weight page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("Warm-up") expect(page.locator('[data-testid="session-detail-item-details-0"]')).to_contain_text("1") expect(page.locator('[data-testid="session-detail-item-details-0"]')).to_contain_text("0") _clean_sessions(page) _clean_exercises(page) _clean_combos(page) def test_reps_weight_defaults(page: Page, app_url: str): """Reps prefill from the exercise's default_reps and weight defaults to 0.""" _go_to_sessions(page, app_url) _clean_sessions(page) _clean_exercises(page) page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) ex_id = _create_exercise_via_repo(page, "Lunges") page.reload() page.wait_for_function( "document.documentElement.getAttribute('data-db-ready') === 'true'", timeout=15000, ) page.click('a[href="#/sessions"]') page.wait_for_timeout(500) page.click('[data-testid="session-new-btn"]') page.wait_for_selector('[data-testid="session-title"]') page.fill('[data-testid="session-title"]', "Defaults Test") # Add exercise page.select_option('[data-testid="session-item-type-select"]', "exercise") page.select_option('[data-testid="session-item-select"]', ex_id) page.click('[data-testid="session-item-add"]') # Verify default values in inputs (_create_exercise_via_repo sets default_reps=10) reps_input = page.locator('[data-testid="session-item-reps-0"]') weight_input = page.locator('[data-testid="session-item-weight-0"]') expect(reps_input).to_have_value("10") expect(weight_input).to_have_value("0") # Save without changing page.click('[data-testid="session-save"]') page.wait_for_selector('[data-testid="session-detail-title"]', timeout=5000) # Verify defaults are shown in detail view (always shown now) expect(page.locator('[data-testid="session-detail-item-0"]')).to_contain_text("Lunges") expect(page.locator('[data-testid="session-detail-item-details-0"]')).to_contain_text("10") expect(page.locator('[data-testid="session-detail-item-details-0"]')).to_contain_text("0") _clean_sessions(page) _clean_exercises(page)