Files
Gondulf/docs/designs/phase-5b-clarifications.md
Phil Skentelbery e1f79af347 feat(test): add Phase 5b integration and E2E tests
Add comprehensive integration and end-to-end test suites:
- Integration tests for API flows (authorization, token, verification)
- Integration tests for middleware chain and security headers
- Integration tests for domain verification services
- E2E tests for complete authentication flows
- E2E tests for error scenarios and edge cases
- Shared test fixtures and utilities in conftest.py
- Rename Dockerfile to Containerfile for Podman compatibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 22:22:04 -07:00

255 lines
7.7 KiB
Markdown

# Phase 5b Implementation Clarifications
This document provides clear answers to the Developer's implementation questions for Phase 5b.
## Questions and Answers
### 1. E2E Browser Automation
**Question**: Should we use Playwright/Selenium for browser automation, or TestClient-based flow simulation?
**Decision**: Use TestClient-based flow simulation.
**Rationale**:
- Simpler and more maintainable - no browser drivers to manage
- Faster execution - no browser startup overhead
- Better CI/CD compatibility - no headless browser configuration
- Sufficient for protocol compliance testing - we're testing OAuth flows, not UI rendering
- Aligns with existing test patterns in the codebase
**Implementation Guidance**:
```python
# Use FastAPI TestClient with session persistence
from fastapi.testclient import TestClient
def test_full_authorization_flow():
client = TestClient(app)
# Simulate full OAuth flow through TestClient
# Parse HTML responses where needed for form submission
```
### 2. Database Fixtures
**Question**: Design shows async SQLAlchemy but codebase uses sync. Should tests use existing sync patterns?
**Decision**: Use existing sync patterns.
**Rationale**:
- Consistency with current codebase (Database class uses sync SQLAlchemy)
- No need to introduce async complexity for testing
- Simpler fixture management
**Implementation Guidance**:
```python
# Keep using sync patterns as in existing database/connection.py
@pytest.fixture
def test_db():
"""Create test database with sync SQLAlchemy."""
db = Database("sqlite:///:memory:")
db.initialize()
yield db
# cleanup
```
### 3. Parallel Test Execution
**Question**: Should pytest-xdist be added for parallel test execution?
**Decision**: No, not for Phase 5b.
**Rationale**:
- Current test suite is small enough for sequential execution
- Avoids complexity of test isolation for parallel runs
- Can be added later if test execution time becomes a problem
- KISS principle - don't add infrastructure we don't need yet
**Implementation Guidance**:
- Run tests sequentially with standard pytest
- Document in test README that parallel execution can be considered for future optimization
### 4. Performance Benchmarks
**Question**: Should pytest-benchmark be added? How to handle potentially flaky CI tests?
**Decision**: No benchmarking in Phase 5b.
**Rationale**:
- Performance testing is not in Phase 5b scope
- Focus on functional correctness and security first
- Performance optimization is premature at this stage
- Can be added in a dedicated performance phase if needed
**Implementation Guidance**:
- Skip any performance-related tests for now
- Focus on correctness and security tests only
### 5. Coverage Thresholds
**Question**: Per-module thresholds aren't natively supported by coverage.py. What approach?
**Decision**: Use global threshold of 80% for Phase 5b.
**Rationale**:
- Simple to implement and verify
- coverage.py supports this natively with `fail_under`
- Per-module thresholds add unnecessary complexity
- 80% is a reasonable target for this phase
**Implementation Guidance**:
```ini
# In pyproject.toml
[tool.coverage.report]
fail_under = 80
```
### 6. Consent Flow Testing
**Question**: Design shows `/consent` with JSON but implementation is `/authorize/consent` with HTML forms. Which to follow?
**Decision**: Follow the actual implementation: `/authorize/consent` with HTML forms.
**Rationale**:
- Test the system as it actually works
- The design document was conceptual; implementation is authoritative
- HTML form testing is more realistic for IndieAuth flows
**Implementation Guidance**:
```python
def test_consent_form_submission():
# POST to /authorize/consent with form data
response = client.post(
"/authorize/consent",
data={
"client_id": "...",
"redirect_uri": "...",
# ... other form fields
}
)
```
### 7. Fixtures Directory
**Question**: Create new `tests/fixtures/` or keep existing `conftest.py` pattern?
**Decision**: Keep existing `conftest.py` pattern.
**Rationale**:
- Consistency with current test structure
- pytest naturally discovers fixtures in conftest.py
- No need to introduce new patterns
- Can organize fixtures within conftest.py with clear sections
**Implementation Guidance**:
```python
# In tests/conftest.py, add new fixtures with clear sections:
# === Database Fixtures ===
@pytest.fixture
def test_database():
"""Test database fixture."""
pass
# === Client Fixtures ===
@pytest.fixture
def registered_client():
"""Pre-registered client fixture."""
pass
# === Authorization Fixtures ===
@pytest.fixture
def valid_auth_code():
"""Valid authorization code fixture."""
pass
```
### 8. CI/CD Workflow
**Question**: Is GitHub Actions workflow in scope for Phase 5b?
**Decision**: No, CI/CD is out of scope for Phase 5b.
**Rationale**:
- Phase 5b focuses on test implementation, not deployment infrastructure
- CI/CD should be a separate phase with its own design
- Keeps Phase 5b scope manageable
**Implementation Guidance**:
- Focus only on making tests runnable via `pytest`
- Document test execution commands in tests/README.md
- CI/CD integration can come later
### 9. DNS Mocking
**Question**: Global patching vs dependency injection override (existing pattern)?
**Decision**: Use dependency injection override pattern (existing in codebase).
**Rationale**:
- Consistency with existing patterns (see get_database, get_verification_service)
- More explicit and controllable
- Easier to reason about in tests
- Avoids global state issues
**Implementation Guidance**:
```python
# Use FastAPI dependency override pattern
def test_with_mocked_dns():
def mock_dns_service():
service = Mock()
service.resolve_txt.return_value = ["expected", "values"]
return service
app.dependency_overrides[get_dns_service] = mock_dns_service
# run test
app.dependency_overrides.clear()
```
### 10. HTTP Mocking
**Question**: Use `responses` library (for requests) or `respx` (for httpx)?
**Decision**: Neither - use unittest.mock for urllib.
**Rationale**:
- The codebase uses urllib.request (see HTMLFetcherService), not requests or httpx
- httpx is only in test dependencies, not used in production code
- Existing tests already mock urllib successfully
- No need to add new mocking libraries
**Implementation Guidance**:
```python
# Follow existing pattern from test_html_fetcher.py
@patch('gondulf.services.html_fetcher.urllib.request.urlopen')
def test_http_fetch(mock_urlopen):
mock_response = MagicMock()
mock_response.read.return_value = b"<html>...</html>"
mock_urlopen.return_value = mock_response
# test the fetch
```
## Summary of Decisions
1. **E2E Testing**: TestClient-based simulation (no browser automation)
2. **Database**: Sync SQLAlchemy (match existing patterns)
3. **Parallel Tests**: No (keep it simple)
4. **Benchmarks**: No (out of scope)
5. **Coverage**: Global 80% threshold
6. **Consent Endpoint**: `/authorize/consent` with HTML forms (match implementation)
7. **Fixtures**: Keep conftest.py pattern
8. **CI/CD**: Out of scope
9. **DNS Mocking**: Dependency injection pattern
10. **HTTP Mocking**: unittest.mock for urllib
## Implementation Priority
Focus on these test categories in order:
1. Integration tests for complete OAuth flows
2. Security tests for timing attacks and injection
3. Error handling tests
4. Edge case coverage
## Key Principle
**Simplicity and Consistency**: Every decision above favors simplicity and consistency with existing patterns over introducing new complexity. The goal is comprehensive testing that works with what we have, not a perfect test infrastructure.
CLARIFICATIONS PROVIDED: Phase 5b - Developer may proceed