All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 12s
- Sidebar: dynamic brand-accent colors, brainstorm section restyled - AI chat general: popup panel with expand/collapse, hides when contextual AI open - AI chat contextual: tabs reordered (Actions first), X close button, height fix - Settings: all tabs restyled, 6 new color presets (sage, terracotta, iron, etc.) - Global color cleanup: emerald/orange hardcoded → brand-accent dynamic - Brainstorm page: orange → brand-accent throughout - PageEntry animation component added to key pages - Floating AI button: bg-brand-accent instead of hardcoded black - i18n: all 15 locales updated with new AI/billing keys - Billing: freemium quota tracking, BYOK, stripe subscription scaffolding - Admin: integrated into new design - AGENTS.md + CLAUDE.md project rules added
168 lines
5.5 KiB
Python
168 lines
5.5 KiB
Python
#!/usr/bin/env python3
|
|
# /// script
|
|
# requires-python = ">=3.10"
|
|
# dependencies = ["pytest>=7.0"]
|
|
# ///
|
|
"""Tests for pre-activate.py"""
|
|
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
from importlib.util import spec_from_file_location, module_from_spec
|
|
|
|
# Load module
|
|
spec = spec_from_file_location(
|
|
"pre_activate",
|
|
Path(__file__).parent.parent / "pre-activate.py",
|
|
)
|
|
mod = module_from_spec(spec)
|
|
spec.loader.exec_module(mod)
|
|
|
|
SAMPLE_CSV = (
|
|
"module,skill,display-name,menu-code,description,action,args,phase,after,before,required,output-location,outputs\n"
|
|
'Suno Band Manager,suno-setup,Setup Suno Module,SU,"Install or update config.",configure,,anytime,,,false,,\n'
|
|
'Suno Band Manager,suno-agent-band-manager,Create Song,CS,"Create a song package.",create-song,,anytime,,,false,,song package\n'
|
|
'Suno Band Manager,suno-agent-band-manager,Refine Song,RS,"Refine a song.",refine-song,,anytime,,,false,,\n'
|
|
'Suno Band Manager,suno-band-profile-manager,Manage Bands,MB,"Manage band profiles.",manage-profiles,,anytime,,,false,,\n'
|
|
)
|
|
|
|
|
|
def test_check_first_run_true(tmp_path):
|
|
"""First run when sidecar doesn't exist."""
|
|
assert mod.check_first_run(tmp_path) is True
|
|
|
|
|
|
def test_check_first_run_false(tmp_path):
|
|
"""Not first run when sidecar exists."""
|
|
sidecar = tmp_path / "_bmad" / "_memory" / "band-manager-sidecar"
|
|
sidecar.mkdir(parents=True)
|
|
assert mod.check_first_run(tmp_path) is False
|
|
|
|
|
|
def test_scaffold_sidecar(tmp_path):
|
|
"""Scaffold creates all expected files."""
|
|
result = mod.scaffold_sidecar(tmp_path)
|
|
assert result["scaffolded"] is True
|
|
assert "access-boundaries.md" in result["files_created"]
|
|
assert "patterns.md" in result["files_created"]
|
|
assert "chronology.md" in result["files_created"]
|
|
|
|
sidecar = tmp_path / "_bmad" / "_memory" / "band-manager-sidecar"
|
|
assert (sidecar / "access-boundaries.md").exists()
|
|
assert (sidecar / "patterns.md").exists()
|
|
assert (sidecar / "chronology.md").exists()
|
|
|
|
|
|
def test_scaffold_idempotent(tmp_path):
|
|
"""Scaffold doesn't overwrite existing files."""
|
|
mod.scaffold_sidecar(tmp_path)
|
|
sidecar = tmp_path / "_bmad" / "_memory" / "band-manager-sidecar"
|
|
|
|
# Write custom content
|
|
(sidecar / "patterns.md").write_text("custom content")
|
|
|
|
result = mod.scaffold_sidecar(tmp_path)
|
|
assert "patterns.md" not in result["files_created"]
|
|
assert (sidecar / "patterns.md").read_text() == "custom content"
|
|
|
|
|
|
def _write_csv(tmp_path, content=SAMPLE_CSV):
|
|
"""Helper to write a test CSV file."""
|
|
csv_path = tmp_path / "module-help.csv"
|
|
csv_path.write_text(content)
|
|
return csv_path
|
|
|
|
|
|
def test_render_menu(tmp_path):
|
|
"""Menu renders correctly from module-help.csv."""
|
|
csv_path = _write_csv(tmp_path)
|
|
|
|
menu = mod.render_menu(csv_path)
|
|
# Setup skill entry should be excluded
|
|
assert "Setup" not in menu
|
|
# Agent and external skill entries should appear
|
|
assert "[CS]" in menu
|
|
assert "[RS]" in menu
|
|
assert "[MB]" in menu
|
|
assert "Create Song" in menu
|
|
|
|
|
|
def test_render_menu_excludes_setup(tmp_path):
|
|
"""Menu does not include the setup skill entry."""
|
|
csv_path = _write_csv(tmp_path)
|
|
menu = mod.render_menu(csv_path)
|
|
assert "[SU]" not in menu
|
|
|
|
|
|
def test_build_routing_table_agent_capabilities(tmp_path):
|
|
"""Agent's own capabilities route to prompt references."""
|
|
csv_path = _write_csv(tmp_path)
|
|
|
|
table = mod.build_routing_table(csv_path)
|
|
assert table["CS"]["type"] == "prompt"
|
|
assert table["CS"]["target"] == "./references/create-song.md"
|
|
assert table["RS"]["type"] == "prompt"
|
|
assert table["RS"]["target"] == "./references/refine-song.md"
|
|
|
|
|
|
def test_build_routing_table_external_skills(tmp_path):
|
|
"""External skill capabilities route to skill invocation."""
|
|
csv_path = _write_csv(tmp_path)
|
|
|
|
table = mod.build_routing_table(csv_path)
|
|
assert table["MB"]["type"] == "skill"
|
|
assert table["MB"]["target"] == "suno-band-profile-manager"
|
|
|
|
|
|
def test_build_routing_table_numeric_keys(tmp_path):
|
|
"""Routing table includes numeric keys for positional access."""
|
|
csv_path = _write_csv(tmp_path)
|
|
|
|
table = mod.build_routing_table(csv_path)
|
|
# First non-setup entry is CS at position 1
|
|
assert table["1"]["name"] == "create-song"
|
|
assert table["2"]["name"] == "refine-song"
|
|
assert table["3"]["name"] == "manage-profiles"
|
|
|
|
|
|
def test_find_module_csv_installed(tmp_path):
|
|
"""Finds CSV at installed location."""
|
|
bmad_dir = tmp_path / "_bmad"
|
|
bmad_dir.mkdir()
|
|
csv_file = bmad_dir / "module-help.csv"
|
|
csv_file.write_text(SAMPLE_CSV)
|
|
|
|
skill_dir = tmp_path / "skills" / "suno-agent-band-manager"
|
|
skill_dir.mkdir(parents=True)
|
|
|
|
result = mod.find_module_csv(tmp_path, skill_dir)
|
|
assert result == csv_file
|
|
|
|
|
|
def test_find_module_csv_setup_assets(tmp_path):
|
|
"""Falls back to setup skill assets when not installed."""
|
|
skills_dir = tmp_path / "skills"
|
|
setup_assets = skills_dir / "suno-setup" / "assets"
|
|
setup_assets.mkdir(parents=True)
|
|
csv_file = setup_assets / "module-help.csv"
|
|
csv_file.write_text(SAMPLE_CSV)
|
|
|
|
skill_dir = skills_dir / "suno-agent-band-manager"
|
|
skill_dir.mkdir(parents=True)
|
|
|
|
result = mod.find_module_csv(tmp_path, skill_dir)
|
|
assert result == csv_file
|
|
|
|
|
|
def test_find_module_csv_not_found(tmp_path):
|
|
"""Returns None when CSV is not found."""
|
|
skill_dir = tmp_path / "skills" / "suno-agent-band-manager"
|
|
skill_dir.mkdir(parents=True)
|
|
|
|
result = mod.find_module_csv(tmp_path, skill_dir)
|
|
assert result is None
|