Files
turnstone/tests/test_markdown.py
T
Patrick Buckley 9be155b97a Quality overhaul: code tooling, CI/CD, architecture diagrams, UI rede… (#1)
* Quality overhaul: code tooling, CI/CD, architecture diagrams, UI redesign, and legacy cleanup

- Add ruff (lint+format) and mypy (strict) with zero errors across 37 source files
- Add GitHub Actions CI (lint, typecheck, test matrix 3.11/3.12/3.13) and PyPI publish workflow
- Create 12 PlantUML architecture diagrams with PNG renders covering all subsystems
- Refresh README and docs with badges, diagram links, and current descriptions
- Refactor test_server_live.py with mock streaming helpers for deterministic CI testing
- Update dependencies to current versions (openai>=2.24, httpx>=0.28, redis>=7.2)

Console dashboard:
- Move state indicators from top cards to fixed bottom status bar with cluster metrics
- Replace flat 50-node list with hostname-prefix grouped nodes (expand/collapse, up to 1000)
- Apply "Instrument Panel" visual redesign: IBM Plex Mono + Outfit fonts, warm amber accent,
  LED glow state indicators, deep charcoal surfaces, WCAG AA contrast compliance
- Add render cache, stale indicator, active filter highlight, loading states

Server web UI:
- Apply matching Instrument Panel aesthetic for visual consistency with console
- Fix branding (pcode → turnstone), extract inline styles to CSS classes
- Rename pcode localStorage keys and history state to turnstone

Legacy cleanup:
- Remove persona-model-specific --persona flag and /persona slash command
- Remove model_identity from chat_template_kwargs (vLLM-specific mechanism)
- Refactor plan agent to use standard developer message instead of model_identity
- Remove dead code (unused date/has_tools variables, noqa suppressions)

* Fix CI typecheck: add mypy overrides for optional sympy/numpy imports

The math sandbox optionally imports sympy and numpy at runtime (try/except
ImportError). In CI these packages are not installed, so mypy raises
import-not-found rather than import-untyped. Add mypy overrides to
ignore missing imports for these optional dependencies.

* Fix Copilot review findings: ARIA role, status bar cache, and pulse opacity

- Change #node-table from role="tree" to role="list" and group elements
  from role="treeitem" to role="listitem" (proper ARIA semantics)
- Include currentView and currentFilter.state in renderStatusBar cache key
  so active pill highlight updates when switching views
- Align pulse animation to 0.35 opacity (already applied in CSS)
2026-03-02 16:55:12 -08:00

81 lines
2.3 KiB
Python

"""Tests for turnstone.ui.markdown — MarkdownRenderer."""
from turnstone.ui.colors import BOLD, CYAN, DIM, ITALIC, MAGENTA
from turnstone.ui.markdown import MarkdownRenderer
class TestMarkdownRenderer:
def setup_method(self):
self.r = MarkdownRenderer()
def test_header_rendering(self):
result = self.r.feed("# Hello\n")
assert BOLD in result
assert MAGENTA in result
assert "Hello" in result
def test_h2_header(self):
result = self.r.feed("## Sub\n")
assert BOLD in result
assert MAGENTA in result
assert "Sub" in result
def test_bold_text(self):
result = self.r.feed("some **bold** text\n")
assert BOLD in result
assert "bold" in result
def test_underscore_bold(self):
result = self.r.feed("some __bold__ text\n")
assert BOLD in result
assert "bold" in result
def test_inline_code(self):
result = self.r.feed("use `code` here\n")
assert CYAN in result
assert "code" in result
def test_code_block_toggle(self):
# Opening fence
result = self.r.feed("```python\n")
assert DIM in result
assert self.r.in_code_block is True
# Content inside code block
result = self.r.feed("x = 1\n")
assert CYAN in result
# Closing fence
result = self.r.feed("```\n")
assert DIM in result
assert self.r.in_code_block is False
def test_bullet_list_cyan(self):
result = self.r.feed("- item one\n")
assert CYAN in result
def test_asterisk_bullet_list(self):
result = self.r.feed("* item one\n")
assert CYAN in result
def test_numbered_list_cyan(self):
result = self.r.feed("1. first\n")
assert CYAN in result
def test_flush_returns_remaining_buffer(self):
# Feed text without a newline
result = self.r.feed("no newline yet")
assert result == "" # No complete line yet
# Flush should return the buffered content
result = self.r.flush()
assert "no newline yet" in result
def test_flush_empty_buffer(self):
assert self.r.flush() == ""
def test_italic_text(self):
result = self.r.feed("some *italic* text\n")
assert ITALIC in result
assert "italic" in result