"""Regression tests for the enhanced commits list page. Covers the four feature areas added to commits_list_page(): Filter bar - test_commits_enhanced_filter_bar_present — filter-bar HTML element present - test_commits_enhanced_author_dropdown_present — author present - test_commits_enhanced_tag_filter_input_present — tag filter present Server-side filtering - test_commits_enhanced_author_filter_narrows_results — ?author= returns only that author's commits - test_commits_enhanced_author_filter_excludes_others — commits by other authors absent - test_commits_enhanced_search_filter_matches_message — ?q= matches substring in commit message - test_commits_enhanced_search_filter_excludes_others — non-matching commits absent - test_commits_enhanced_date_from_filter — ?dateFrom= excludes older commits - test_commits_enhanced_tag_filter_matches_tag — ?tag=emotion:funky matches message substring Compare mode - test_commits_enhanced_compare_toggle_btn_present — compare-toggle-btn button present - test_commits_enhanced_compare_strip_present — compare-strip container present - test_commits_enhanced_compare_check_inputs_present — compare-check checkboxes per row - test_commits_enhanced_compare_js_function — toggleCompareMode() JS function present Metadata badges (client-side JS) - test_commits_enhanced_meta_badges_container_present — meta-badges span present per row - test_commits_enhanced_badge_js_extract_function — extractBadges() JS function present - test_commits_enhanced_chip_css_classes_present — chip-tempo / chip-key / chip-emotion CSS defined Mini-lane - test_commits_enhanced_dag_merge_arm_present — dag-merge-arm element on merge commits - test_commits_enhanced_mini_lane_dag_col_present — dag-col column present Pagination with active filters - test_commits_enhanced_pagination_preserves_filters — page links carry active filter params """ from __future__ import annotations from datetime import datetime, timezone import pytest from httpx import AsyncClient from sqlalchemy.ext.asyncio import AsyncSession from musehub.core.genesis import compute_branch_id, compute_identity_id, compute_repo_id from musehub.db.musehub_repo_models import MusehubBranch, MusehubCommit, MusehubCommitRef, MusehubRepo # ── Constants ───────────────────────────────────────────────────────────────── _OWNER = "enhancedowner" _SLUG = "enhanced-commits" _SHA_ALICE_1 = "a1" + "0" * 38 _SHA_ALICE_2 = "a2" + "0" * 38 _SHA_BOB_1 = "b1" + "0" * 38 _SHA_MERGE = "cc" + "0" * 38 # ── Seed helpers ────────────────────────────────────────────────────────────── async def _seed_repo(db: AsyncSession) -> str: """Seed a public repo with 4 commits from 2 authors and return repo_id.""" owner_id = compute_identity_id(_OWNER.encode()) created_at = datetime.now(tz=timezone.utc) repo = MusehubRepo( repo_id=compute_repo_id(owner_id, _SLUG, "code", created_at.isoformat()), name=_SLUG, owner=_OWNER, slug=_SLUG, visibility="public", owner_user_id=owner_id, created_at=created_at, updated_at=created_at, ) db.add(repo) await db.flush() repo_id = str(repo.repo_id) branch = MusehubBranch(branch_id=compute_branch_id(repo_id, "main"), repo_id=repo_id, name="main", head_commit_id=_SHA_MERGE) db.add(branch) # Alice: two commits with music metadata in messages db.add(MusehubCommit(commit_id=_SHA_ALICE_1, branch="main", parent_ids=[], message="Add walking bass line 120 BPM Cm emotion:funky", author="alice", timestamp=datetime(2026, 1, 10, tzinfo=timezone.utc))) db.add(MusehubCommitRef(repo_id=repo_id, commit_id=_SHA_ALICE_1)) db.add(MusehubCommit(commit_id=_SHA_ALICE_2, branch="main", parent_ids=[_SHA_ALICE_1], message="Refine rhodes chord voicings stage:chorus", author="alice", timestamp=datetime(2026, 2, 15, tzinfo=timezone.utc))) db.add(MusehubCommitRef(repo_id=repo_id, commit_id=_SHA_ALICE_2)) # Bob: one commit db.add(MusehubCommit(commit_id=_SHA_BOB_1, branch="main", parent_ids=[_SHA_ALICE_2], message="Add jazz drums groove 90 BPM Gm", author="bob", timestamp=datetime(2026, 3, 1, tzinfo=timezone.utc))) db.add(MusehubCommitRef(repo_id=repo_id, commit_id=_SHA_BOB_1)) # Merge commit db.add(MusehubCommit(commit_id=_SHA_MERGE, branch="main", parent_ids=[_SHA_ALICE_2, _SHA_BOB_1], message="Merge feat/drums into main", author="alice", timestamp=datetime(2026, 3, 2, tzinfo=timezone.utc))) db.add(MusehubCommitRef(repo_id=repo_id, commit_id=_SHA_MERGE)) await db.commit() return repo_id def _url(path: str = "") -> str: return f"/{_OWNER}/{_SLUG}/commits{path}" # ── Filter bar HTML ─────────────────────────────────────────────────────────── async def test_commits_enhanced_filter_bar_present( client: AsyncClient, db_session: AsyncSession ) -> None: """filter-bar container is rendered on the commits list page.""" await _seed_repo(db_session) resp = await client.get(_url()) assert resp.status_code == 200 assert "filter-bar" in resp.text async def test_commits_enhanced_author_dropdown_present( client: AsyncClient, db_session: AsyncSession ) -> None: """Author