# S02: Post-Processing + Output Formats (SVG, DXF, JSON) — UAT

**Milestone:** M001
**Written:** 2026-03-26T04:41:57.970Z

# S02: Post-Processing + Output Formats (SVG, DXF, JSON) — UAT

**Milestone:** M001
**Written:** 2026-03-26

## UAT Type

- UAT mode: artifact-driven
- Why this mode is sufficient: All endpoints return structured data (SVG/DXF/JSON) that can be validated programmatically. 169 automated tests cover functional correctness, format validity, and edge cases.

## Preconditions

- Engine virtualenv exists at `engine/.venv/` with all dependencies installed (ezdxf, numpy, opencv, etc.)
- Tests run with `cd engine && .venv/bin/python -m pytest tests/ -v` (NOT bare `python` — see P002)

## Smoke Test

```bash
cd engine && .venv/bin/python -m pytest tests/test_api.py -v
```
Expected: 35 tests pass, exit code 0.

## Test Cases

### 1. /engine/trace returns valid SVG with post-processing metadata

1. POST to /engine/trace with a PNG image, mode=potrace, output_format=svg
2. Check response JSON has `output` (SVG string), `format` ("svg"), `metadata` object
3. **Expected:** metadata contains path_count > 0, node_count_total > 0, open_paths >= 0, island_count >= 0, processing_ms > 0

### 2. /engine/trace returns valid DXF binary

1. POST to /engine/trace with a PNG image, mode=potrace, output_format=dxf
2. Check response content-type is "application/dxf"
3. Check X-Kerf-Metadata header is valid JSON with path_count, node_count_total
4. Check response body starts with "0\nSECTION" (DXF header)
5. **Expected:** Valid AC1015 DXF file with LWPOLYLINE entities

### 3. /engine/trace returns valid JSON output

1. POST to /engine/trace with a PNG image, mode=potrace, output_format=json
2. Check response JSON has `output.paths` array and `output.metadata`
3. Check each path has `commands` array with M/L/Z entries and `properties` dict
4. **Expected:** JSON structure with is_closed, is_island, node_count, area per path

### 4. /engine/trace works with VTracer mode

1. POST to /engine/trace with a PNG image, mode=vtracer, output_format=svg
2. **Expected:** Valid SVG output with metadata, different path structure from potrace

### 5. /engine/simplify reduces node count

1. POST to /engine/simplify with a complex SVG file, epsilon=2.0
2. Compare node_count_total in response metadata
3. **Expected:** node_count_total is less than original SVG path node count

### 6. /engine/simplify supports all output formats

1. POST to /engine/simplify with SVG file, output_format=dxf
2. POST to /engine/simplify with SVG file, output_format=json
3. POST to /engine/simplify with SVG file, output_format=svg
4. **Expected:** All three return valid output in their respective formats

### 7. Island detection identifies interior paths

1. Trace or simplify an image/SVG with interior holes (e.g., letter "O" shape)
2. Check JSON output for paths with `is_island: true`
3. Check DXF output for entities on the "ISLANDS" layer
4. **Expected:** Interior counter-paths correctly flagged as islands

## Edge Cases

### Empty file upload

1. POST to /engine/trace with an empty file
2. **Expected:** HTTP 422 with detail "Uploaded file is empty"

### Invalid output_format

1. POST to /engine/trace with output_format=pdf
2. **Expected:** HTTP 422 with detail listing valid formats (dxf, json, svg)

### Non-SVG file to /engine/simplify

1. POST to /engine/simplify with a PNG file
2. **Expected:** HTTP 422 with detail "File does not appear to be a valid SVG"

### Binary file to /engine/simplify

1. POST to /engine/simplify with random binary data
2. **Expected:** HTTP 422 with detail "File is not valid UTF-8 text"

### Default epsilon on /engine/simplify

1. POST to /engine/simplify without specifying epsilon
2. **Expected:** Uses default epsilon=1.0, returns valid output

## Failure Signals

- Any test in `test_api.py`, `test_postprocess.py`, or `test_output.py` fails
- DXF output doesn't start with "0\nSECTION" (malformed DXF)
- JSON output missing `commands` or `properties` in path objects
- X-Kerf-Metadata header missing or invalid JSON on DXF responses
- node_count_total or path_count is 0 for non-trivial inputs

## Not Proven By This UAT

- Visual quality of DXF output in actual CAD software (Inkscape, AutoCAD)
- Curve fidelity after bezier-to-polyline linearization
- Performance under large/complex SVG inputs (no load testing)
- viewBox/transform matrix handling in SVG path parsing

## Notes for Tester

- ezdxf emits pyparsing deprecation warnings during tests — these are harmless library-internal warnings, not bugs
- Tests generate images programmatically via numpy (pattern P001) — no fixture files needed
- Always use `.venv/bin/python -m pytest`, never bare `python` (pattern P002)
