This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Timmy-time-dashboard/tox.ini
Alexander Whitestone 622a6a9204 polish: extract inline CSS, add connection status, panel macro, favicon, ollama cache, toast system (#164)
Major:
- Extract all inline <style> blocks from 22 Jinja2 templates into
  static/css/mission-control.css — single cacheable stylesheet
- Add tox lint check that fails on inline <style> in templates

Minor:
1. Connection status indicator in topbar (green/amber/red dot) reflecting
   WebSocket + Ollama reachability, with auto-reconnect
2. Jinja2 {% macro panel(title) %} in macros.html — eliminates repeated
   .card.mc-panel markup; index.html converted as example
3. SVG favicon (purple T + orange dot)
4. 30-second TTL cache on _check_ollama() to avoid blocking the event loop
   on every health poll (asyncio.to_thread was already in place)
5. Toast notification system (McToast.show) for transient status messages —
   wired into connection status for Ollama/WebSocket state changes

Enforcement:
- CLAUDE.md updated with conventions 11-14 (no inline CSS, use panel macro,
  use toasts, never block the event loop)
- tox lint + pre-push environments now fail on inline <style> blocks

https://claude.ai/code/session_014FQ785MQdyJQ4BAXrRSo9w

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-11 09:52:57 -04:00

161 lines
6.1 KiB
INI

[tox]
envlist = lint, unit, integration
no_package = true
# ── Base ─────────────────────────────────────────────────────────────────────
[testenv]
allowlist_externals = timeout, perl, docker, mkdir, bash, grep
commands_pre = pip install -e ".[dev]" --quiet
setenv =
TIMMY_TEST_MODE = 1
TIMMY_DISABLE_CSRF = 1
TIMMY_SKIP_EMBEDDINGS = 1
# ── Lint & Format ────────────────────────────────────────────────────────────
[testenv:lint]
description = Check formatting (black), import order (isort), security (bandit), no inline CSS
commands_pre =
deps =
black
isort
bandit>=1.8.0
commands =
black --check --line-length 100 src/ tests/
isort --check-only --profile black --line-length 100 src/ tests/
bandit -r src/ -ll -s B101,B104,B307,B310,B324,B601,B608 -q
bash -c 'files=$(grep -rl "<style" src/dashboard/templates/ --include="*.html" 2>/dev/null); if [ -n "$files" ]; then echo "ERROR: inline <style> blocks found — move CSS to static/css/mission-control.css:"; echo "$files"; exit 1; fi; echo "No inline CSS — OK"'
[testenv:format]
description = Auto-format code with black + isort
commands_pre =
deps =
black
isort
commands =
black --line-length 100 src/ tests/
isort --profile black --line-length 100 src/ tests/
[testenv:typecheck]
description = Static type checking with mypy
commands =
mypy src --ignore-missing-imports --no-error-summary
# ── Test Environments ────────────────────────────────────────────────────────
[testenv:unit]
description = Fast tests — excludes e2e, functional, and external services
commands =
pytest tests/ -q --tb=short \
--ignore=tests/e2e \
--ignore=tests/functional \
-m "not ollama and not docker and not selenium and not external_api and not skip_ci" \
-n auto --dist worksteal
[testenv:integration]
description = Integration tests (marked with @pytest.mark.integration)
commands =
pytest tests/ -q --tb=short \
-m "integration and not ollama and not docker and not selenium and not external_api" \
-n auto --dist worksteal
[testenv:functional]
description = Functional tests — real HTTP, no mocking (excl slow + selenium)
commands =
pytest tests/functional/ -q --tb=short -n0 \
-m "not slow and not selenium"
[testenv:e2e]
description = End-to-end tests — full system, may be slow
commands =
pytest tests/e2e/ -q --tb=short -n0
[testenv:fast]
description = All tests except e2e, functional, and external
commands =
pytest tests/ -q --tb=short \
--ignore=tests/e2e \
--ignore=tests/functional \
-m "not ollama and not docker and not selenium and not external_api" \
-n auto --dist worksteal
[testenv:ollama]
description = Live LLM tests via Ollama (requires running Ollama)
commands =
pytest tests/ -q --tb=short -m ollama --timeout=120
# ── CI / Coverage ────────────────────────────────────────────────────────────
[testenv:ci]
description = CI test suite with coverage + JUnit XML (mirrors GitHub Actions)
commands =
mkdir -p reports
pytest tests/ \
--cov=src \
--cov-report=term-missing \
--cov-report=xml:reports/coverage.xml \
--cov-fail-under=73 \
--junitxml=reports/junit.xml \
-p no:xdist \
-m "not ollama and not docker and not selenium and not external_api"
[testenv:coverage]
description = Full coverage report (terminal + XML)
commands =
pytest tests/ -q --tb=short \
--cov=src \
--cov-report=term-missing \
--cov-report=xml \
--cov-fail-under=73 \
-p no:xdist \
-m "not ollama and not docker and not selenium and not external_api"
[testenv:coverage-html]
description = Coverage with HTML report
commands =
pytest tests/ -q --tb=short \
--cov=src \
--cov-report=term-missing \
--cov-report=html \
--cov-fail-under=73 \
-p no:xdist \
-m "not ollama and not docker and not selenium and not external_api"
# ── Pre-push (mirrors CI exactly) ────────────────────────────────────────────
[testenv:pre-push]
description = Local gate — lint + full CI suite (same as GitHub Actions)
deps =
black
isort
bandit>=1.8.0
commands =
black --check --line-length 100 src/ tests/
isort --check-only --profile black --line-length 100 src/ tests/
bandit -r src/ -ll -s B101,B104,B307,B310,B324,B601,B608 -q
bash -c 'files=$(grep -rl "<style" src/dashboard/templates/ --include="*.html" 2>/dev/null); if [ -n "$files" ]; then echo "ERROR: inline <style> blocks found — move CSS to static/css/mission-control.css:"; echo "$files"; exit 1; fi; echo "No inline CSS — OK"'
mkdir -p reports
pytest tests/ \
--cov=src \
--cov-report=term-missing \
--cov-report=xml:reports/coverage.xml \
--cov-fail-under=73 \
--junitxml=reports/junit.xml \
-p no:xdist \
-m "not ollama and not docker and not selenium and not external_api"
# ── Dev Server ───────────────────────────────────────────────────────────────
[testenv:dev]
description = Start dashboard with auto-reload (local development)
commands =
uvicorn dashboard.app:app --reload --host 0.0.0.0 --port 8000
# ── All Tests (parallel) ─────────────────────────────────────────────────────
[testenv:all]
description = Run all tests in parallel
commands =
pytest tests/ -q --tb=short -n auto --dist worksteal