diff --git a/CLAUDE.md b/CLAUDE.md index 60829bc..99c5cbb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,6 +4,8 @@ Auto-generated from all feature plans. Last updated: 2025-10-15 ## Active Technologies - Python 3.11+ + Flask (web framework), no CSS frameworks, no JavaScript libraries (001-build-an-application) +- Python 3.11+ + Flask 3.0+, Jinja2 (built-in) (002-product-list) +- File-based (data/products/*/config.yaml - existing) (002-product-list) ## Project Structure ``` @@ -19,7 +21,8 @@ cd src [ONLY COMMANDS FOR ACTIVE TECHNOLOGIES][ONLY COMMANDS FOR ACTIVE TECHNOLO Python 3.11+: Follow standard conventions ## Recent Changes +- 002-product-list: Added Python 3.11+ + Flask 3.0+, Jinja2 (built-in) - 001-build-an-application: Added Python 3.11+ + Flask (web framework), no CSS frameworks, no JavaScript libraries - \ No newline at end of file + diff --git a/specs/002-product-list/contracts/landing-page.yaml b/specs/002-product-list/contracts/landing-page.yaml new file mode 100644 index 0000000..b92e40d --- /dev/null +++ b/specs/002-product-list/contracts/landing-page.yaml @@ -0,0 +1,101 @@ +openapi: 3.0.3 +info: + title: Reklamator Landing Page API + version: 1.0.0 + description: Product selection landing page contract for feature 002-product-list + +paths: + /: + get: + summary: Landing page - list active products + description: | + Display a landing page showing all active products available for feedback submission. + Products are sorted alphabetically by name (case-insensitive), with product_id as tiebreaker. + operationId: getLandingPage + tags: + - Landing Page + responses: + '200': + description: HTML page with product list or empty state message + content: + text/html: + schema: + type: string + description: Server-rendered HTML page + examples: + with_products: + summary: Multiple active products displayed + value: | + + + Select a Product + +

Select a Product for Feedback

+ + + + + no_products: + summary: No active products (empty state) + value: | + + + Select a Product + +

Select a Product for Feedback

+

No products are currently accepting feedback. Please check back later.

+ + + + product_without_description: + summary: Product without description (no placeholder text) + value: | + + + Select a Product + +

Select a Product for Feedback

+ + + + +components: + schemas: + # No request/response schemas needed (HTML rendering) + # Product data comes from file-based storage, not API request body + +# Contract Test Scenarios +# These scenarios should be covered in tests/contract/test_landing_routes.py: +# +# 1. GET / with active products → 200 OK with product list HTML +# 2. GET / with no active products → 200 OK with empty state message +# 3. GET / with mixed active/archived → 200 OK showing only active +# 4. GET / verifies alphabetical sorting (name, then product_id) +# 5. GET / excludes products with missing submission_url_slug +# 6. GET / properly escapes product names (XSS prevention) +# 7. GET / displays descriptions when present +# 8. GET / omits description placeholder when missing +# 9. GET / accessible to anonymous users +# 10. GET / accessible to authenticated users (same behavior) + +# Success Criteria Validation: +# - SC-001: Page contains clickable links to /submit/{slug} +# - SC-002: Response time <1s for up to 100 products +# - SC-004: Existing /submit/{slug} routes still functional (backwards compatibility) +# - SC-005: Empty state message displayed when no active products +# - SC-006: HTML escaping prevents XSS (test with " + # Assert: HTML is escaped, script not executed + pass + +@pytest.mark.contract +def test_get_landing_page_missing_slug(client, temp_data_dir): + """T306: GET / excludes products with missing submission_url_slug""" + # Setup: Product with submission_url_slug = None + # Assert: Product not shown in list + pass +``` + +--- + +### 5. Write Integration Tests + +**File**: `tests/integration/test_landing_flow.py` (new file) + +**User journey test**: + +```python +@pytest.mark.integration +def test_landing_to_submission_flow(client, temp_data_dir): + """T307: Complete flow - landing page → product selection → submission form""" + # Step 1: Visit landing page, see products + # Step 2: Click product link + # Step 3: Verify redirected to /submit/{slug} + pass +``` + +--- + +## Key Implementation Notes + +### XSS Prevention +- ✅ Jinja2 auto-escaping handles product names and descriptions +- ✅ No manual HTML escaping needed +- ✅ Test with `