import re import subprocess from pathlib import Path ROOT = Path(__file__).resolve().parent.parent SKILLS_JS = (ROOT / "static/js/skills.js").read_text(encoding="utf-8") METRICS_JS = (ROOT / "static/js/skillsMetrics.js").read_text(encoding="utf-8") STYLE = (ROOT / "static/style.css").read_text(encoding="utf-8") INDEX = (ROOT / "static/index.html").read_text(encoding="utf-8") def test_skills_cards_show_saved_turn_estimates_from_audit(): assert "function _turnSavingsHtml" in SKILLS_JS assert "auditNumber(sk, 'saved_turns')" in SKILLS_JS assert "auditNumber(sk, 'saved_tool_calls')" in SKILLS_JS assert "saves ${turns}t" in SKILLS_JS assert "_skillStatsHtml(sk)" in SKILLS_JS assert "skill-turns-saved" in STYLE def test_skills_can_sort_by_saved_turns(): assert '' in INDEX assert "_skillsSort === 'saved-turns'" in SKILLS_JS assert "const bt = auditNumber(b, 'saved_turns')" in SKILLS_JS assert "const at = auditNumber(a, 'saved_turns')" in SKILLS_JS def test_skills_summary_surfaces_audit_health_and_quick_filters(): assert '
s.name), ['fast']); assert.deepEqual(filterSkillsByQuickFilter(skills, 'approved').map(s => s.name), ['fast', 'slow']); assert.deepEqual(filterSkillsByQuickFilter(skills, 'unaudited').map(s => s.name), ['drafty']); assert.deepEqual(filterSkillsByQuickFilter(skills, 'review').map(s => s.name), ['dup', 'broad-zero']); assert.deepEqual(filterSkillsByQuickFilter(skills, 'draft').map(s => s.name), ['drafty', 'dup', 'broad-zero']); """ result = subprocess.run( ["node", "--input-type=module", "-e", script], cwd=ROOT, text=True, capture_output=True, check=False, ) assert result.returncode == 0, result.stderr def test_broad_scope_skill_pill_is_neutral_not_strong_red(): assert "kind === 'trivial' ? 'broad'" in SKILLS_JS block = re.search( r"\.skill-necessity-trivial\s*\{(?P.*?)\n\}", STYLE, flags=re.S, ) assert block is not None assert "var(--color-danger" not in block.group("body") def test_skills_bundle_is_cache_busted_for_saved_turn_ui(): service_worker = (ROOT / "static/sw.js").read_text(encoding="utf-8") index_version = re.search(r"/static/js/skills\.js\?v=([A-Za-z0-9_-]+)", INDEX) sw_version = re.search(r"/static/js/skills\.js\?v=([A-Za-z0-9_-]+)", service_worker) assert index_version and sw_version assert index_version.group(1) == sw_version.group(1) def test_skill_card_statuses_are_compact_and_unambiguous(): assert 'class="skill-card-title-row"' in SKILLS_JS assert "sk.source === 'builtin' ? _sourcePill(sk) : ''" in SKILLS_JS assert 'class="memory-cat-badge skill-status-pill skill-status-published"' in SKILLS_JS assert "skillIsApproved(sk, _skillApprovalThreshold) ? _statusPill(sk) : ''" in SKILLS_JS assert 'Queued for automatic skill check' in SKILLS_JS assert 'Eligible drafts are reviewed automatically.' in SKILLS_JS assert 'esc(model + reason)' in SKILLS_JS assert ".skill-status-published" in STYLE assert ".skill-card:not(.doclib-card-expanded) .skill-card-tags { display: none; }" in STYLE def test_skills_summary_follows_the_search_toolbar(): toolbar_end = INDEX.index('
\n
sk.source !== 'builtin' && sk.status !== 'binned')" in SKILLS_JS script = """ import assert from 'node:assert/strict'; import { filterSkillsByQuickFilter, skillsSummaryMetrics, } from './static/js/skillsMetrics.js'; const skills = [ { name: 'core', source: 'builtin', status: 'published', confidence: 1 }, { name: 'draft', source: 'user', status: 'draft', confidence: 0.5 }, ]; assert.deepEqual(skillsSummaryMetrics(skills, 0.85), { total: 2, approved: 1, proven: 1, needsAudit: 1, audited: 0, review: 0, drafts: 1, binned: 0, savedTurns: 0, }); assert.deepEqual(filterSkillsByQuickFilter(skills, 'approved').map(s => s.name), []); assert.deepEqual(filterSkillsByQuickFilter(skills, 'builtin').map(s => s.name), ['core']); assert.deepEqual(filterSkillsByQuickFilter(skills, 'unaudited').map(s => s.name), ['draft']); """ result = subprocess.run( ["node", "--input-type=module", "-e", script], cwd=ROOT, text=True, capture_output=True, check=False, ) assert result.returncode == 0, result.stderr