Implement MVP: Anonymous feedback submission (User Story 1)
Complete implementation of Phase 1-3 (64 tasks): - Phase 1: Project setup with Flask, pytest, configuration - Phase 2: Core infrastructure (auth, models, services, testing) - Phase 3: Anonymous feedback submission with file uploads Features: - Anonymous feedback submission (text and/or up to 3 file attachments) - Multi-language support (any language accepted) - File validation (type, size) and virus scanning (ClamAV) - Product management with active/archived status - File-based storage with YAML metadata - User authentication system (Flask-Login) - CSRF protection and rate limiting - Test coverage: 10 passing tests (contract + integration) Security: - No IP address logging (FR-055 compliance) - File type whitelist and size limits (10MB max) - Virus scanning with graceful degradation - Filename sanitization and secure storage Test Results: - 8 contract tests passed - 2 integration tests passed - End-to-end workflow verified 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
"""Pytest configuration and fixtures"""
|
||||
import os
|
||||
import pytest
|
||||
import tempfile
|
||||
import shutil
|
||||
from app import create_app
|
||||
from app.models.user import User
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app():
|
||||
"""Create application for testing"""
|
||||
app = create_app('testing')
|
||||
|
||||
# Create temporary data directory
|
||||
with app.app_context():
|
||||
os.makedirs(app.config['DATA_DIR'], exist_ok=True)
|
||||
|
||||
yield app
|
||||
|
||||
# Cleanup temporary directory
|
||||
with app.app_context():
|
||||
if os.path.exists(app.config['DATA_DIR']):
|
||||
shutil.rmtree(app.config['DATA_DIR'])
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client(app):
|
||||
"""Create test client"""
|
||||
return app.test_client()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def runner(app):
|
||||
"""Create test CLI runner"""
|
||||
return app.test_cli_runner()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def admin_user(app):
|
||||
"""Create administrator user for testing"""
|
||||
with app.app_context():
|
||||
user = User.create(
|
||||
username='admin',
|
||||
email='admin@example.com',
|
||||
password='admin123',
|
||||
role='administrator'
|
||||
)
|
||||
yield user
|
||||
# Cleanup
|
||||
user.delete()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def product_owner_user(app):
|
||||
"""Create product owner user for testing"""
|
||||
with app.app_context():
|
||||
user = User.create(
|
||||
username='owner',
|
||||
email='owner@example.com',
|
||||
password='owner123',
|
||||
role='product_owner',
|
||||
product_ids=['prod_0001']
|
||||
)
|
||||
yield user
|
||||
# Cleanup
|
||||
user.delete()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def authenticated_admin_client(client, admin_user):
|
||||
"""Create authenticated admin client"""
|
||||
with client:
|
||||
client.post('/auth/login', data={
|
||||
'username': 'admin',
|
||||
'password': 'admin123'
|
||||
}, follow_redirects=True)
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def authenticated_owner_client(client, product_owner_user):
|
||||
"""Create authenticated product owner client"""
|
||||
with client:
|
||||
client.post('/auth/login', data={
|
||||
'username': 'owner',
|
||||
'password': 'owner123'
|
||||
}, follow_redirects=True)
|
||||
yield client
|
||||
Reference in New Issue
Block a user