# 02 - Comparison Test Infrastructure

## Goal
Set up test fixtures and reference rendering infrastructure EARLY so every subsequent task can validate against mmdc output. Build the comparison harness before writing our own renderer.

## Dependencies
- Task 01 (project setup) must be `.done.md` first -- we need a working `pyproject.toml`, `pytest` config, and package structure before adding tests.
- Node.js + `@mermaid-js/mermaid-cli` (external, for generating reference SVGs; not required at test runtime).

## Tasks

### Reference Rendering Setup
- [ ] Script/Makefile target to install mermaid-cli: `npm install -g @mermaid-js/mermaid-cli`
- [ ] Script to render all test fixtures with mmdc:
  ```bash
  mmdc -i fixture.mmd -o reference.svg -t default --configFile config-deterministic.json
  ```
- [ ] Store reference SVGs in `tests/reference/` (committed to repo)
- [ ] Config for deterministic output (disable animations, fixed random seed) stored at a known path (e.g., `tests/mmdc-config.json`)

### Test Fixtures
- [ ] Create a `tests/fixtures/` directory with `.mmd` files
- [ ] At least 4 fixture files covering a meaningful spread:
  - A simple flowchart (2-3 nodes, basic arrows)
  - A flowchart with multiple node shapes
  - A flowchart with subgraphs
  - A flowchart with styling (classDef)
- [ ] Each `.mmd` fixture must have a corresponding `.svg` file in `tests/reference/` generated by mmdc

### Structural Comparison Utilities
- [ ] A Python module (e.g., `tests/comparison.py` or `tests/conftest.py` helpers) that:
  - Parses an SVG file as XML (using `xml.etree.ElementTree` or `lxml`)
  - Extracts node count from the SVG
  - Extracts edge count from the SVG
  - Extracts label/text content from the SVG
- [ ] A comparison function that takes two SVG files (reference and ours) and returns a structured diff (what nodes/edges/labels are missing or extra)

### pytest Integration
- [ ] A `comparison` pytest marker registered in `pyproject.toml` (or `pytest.ini`)
- [ ] Parametrized test(s) that discover all `.mmd` files in `tests/fixtures/` automatically
- [ ] Clear failure messages showing what differs (e.g., "Expected 5 nodes, found 3; missing labels: ['Start', 'End']")
- [ ] Tests must be skippable gracefully when no pymermaid renderer exists yet (since this task lands before the renderer). The harness should be ready to plug in a renderer in later tasks.

### Visual Comparison (optional, nice-to-have)
- [ ] Rasterize both SVGs to PNG (using cairosvg or resvg)
- [ ] Compute pixel-level difference
- [ ] Report similarity percentage
- [ ] Threshold: >90% similarity for basic flowcharts

## Acceptance Criteria

- [ ] Directory `tests/fixtures/` exists and contains at least 4 `.mmd` fixture files
- [ ] Directory `tests/reference/` exists and contains a matching `.svg` file for each fixture, generated by mmdc
- [ ] A deterministic mmdc config file exists (e.g., `tests/mmdc-config.json`) that disables animations
- [ ] A script or Makefile target exists to regenerate reference SVGs from fixtures (documented in a comment or docstring)
- [ ] `from tests.comparison import parse_svg_nodes, parse_svg_edges, parse_svg_labels` (or equivalent import path) works and these functions accept an SVG file path and return structured data
- [ ] `parse_svg_nodes` returns a count or list of node elements from a reference SVG
- [ ] `parse_svg_edges` returns a count or list of edge/path elements from a reference SVG
- [ ] `parse_svg_labels` returns a list of text strings found in a reference SVG
- [ ] A structural comparison function exists that compares two SVGs and returns differences
- [ ] The `comparison` marker is registered so `pytest -m comparison` does not emit an "Unknown marker" warning
- [ ] `uv run pytest -m comparison` collects parametrized test cases (one per fixture file)
- [ ] Tests are currently expected to skip or xfail (since no renderer exists yet) -- they must not error out
- [ ] Adding a new `.mmd` file to `tests/fixtures/` (with a corresponding reference SVG) automatically adds a new parametrized test case without modifying Python code
- [ ] `uv run pytest tests/` (without the comparison marker) does not fail due to this infrastructure

## Test Scenarios

### Unit: SVG parsing utilities
- Parse a known reference SVG and verify `parse_svg_nodes` returns the expected count of node elements
- Parse a known reference SVG and verify `parse_svg_labels` returns expected text strings (e.g., "Start", "End", "Process")
- Parse a known reference SVG and verify `parse_svg_edges` returns a non-zero count
- Call parse functions on an empty/minimal SVG and verify they return empty results without crashing

### Unit: Structural comparison
- Compare a reference SVG against itself -- expect no differences (identical)
- Compare a reference SVG against a modified SVG with a missing node -- expect the diff to report the missing node/label
- Compare a reference SVG against a modified SVG with extra content -- expect the diff to report extra elements

### Integration: Fixture discovery
- Verify that the parametrized test collects exactly as many test cases as there are `.mmd` files in `tests/fixtures/`
- Verify that `pytest -m comparison` selects only the comparison tests, not other tests
- Verify that tests skip or xfail gracefully when no pymermaid renderer is available

### Integration: Reference SVGs
- Verify each `.mmd` file in `tests/fixtures/` has a corresponding `.svg` in `tests/reference/`
- Verify the reference SVGs are valid XML (parseable without errors)

## Note
This task is intentionally early. The reference SVGs and comparison utilities are created BEFORE our renderer exists. As each rendering task (07-11) lands, the comparison tests start passing incrementally.

## Estimated Complexity
Medium - scripting and test infrastructure, not algorithmic.
