"""Contract tests for submission routes""" import pytest import io import os import yaml @pytest.fixture def test_product(app): """Create a test product""" with app.app_context(): # Create test product directory and config product_dir = os.path.join(app.config['DATA_DIR'], 'products', 'test-product') os.makedirs(product_dir, exist_ok=True) # Create product config config_file = os.path.join(product_dir, 'config.yaml') config_data = { 'product_id': 'test-product', 'name': 'Test Product', 'submission_url_slug': 'test-product', 'owner_language': 'en', 'assigned_owner_ids': ['usr_0001'], 'status': 'active' } with open(config_file, 'w') as f: yaml.dump(config_data, f) yield 'test-product' @pytest.mark.contract def test_get_submission_form(client, test_product): """T030: Contract test for GET /submit/{product_slug} Expected: 200 OK with HTML form containing textarea and file inputs """ response = client.get('/submit/test-product') assert response.status_code == 200 assert b'3 files rejection (400) Expected: 400 Bad Request - maximum 3 files allowed """ data = { 'files': [ (io.BytesIO(b'file1'), 'file1.txt'), (io.BytesIO(b'file2'), 'file2.txt'), (io.BytesIO(b'file3'), 'file3.txt'), (io.BytesIO(b'file4'), 'file4.txt') ] } response = client.post('/submit/test-product', data=data, content_type='multipart/form-data') assert response.status_code == 400 assert b'maximum' in response.data.lower() or b'3' in response.data @pytest.mark.contract def test_large_file_rejected(client, test_product): """T036: Contract test for >10MB file rejection (413) Expected: 413 Request Entity Too Large """ # Create a file larger than 10MB large_content = b'x' * (11 * 1024 * 1024) # 11MB data = { 'files': [ (io.BytesIO(large_content), 'large.txt') ] } response = client.post('/submit/test-product', data=data, content_type='multipart/form-data') # Flask will reject this with 413 due to MAX_CONTENT_LENGTH assert response.status_code == 413 @pytest.mark.contract def test_unsupported_file_type_rejected(client, test_product): """T037: Contract test for unsupported file type rejection (400) Expected: 400 Bad Request - file type not allowed """ data = { 'files': [ (io.BytesIO(b'#!/bin/bash\necho malicious'), 'script.sh') ] } response = client.post('/submit/test-product', data=data, content_type='multipart/form-data') assert response.status_code == 400 assert b'not allowed' in response.data.lower() or b'type' in response.data.lower() @pytest.mark.contract def test_rate_limiting(client, test_product, app): """T038: Contract test for rate limiting (429 after 10 submissions) Expected: 429 Too Many Requests after exceeding rate limit """ # Skip if rate limiting is disabled if not app.config.get('RATELIMIT_ENABLED'): pytest.skip('Rate limiting disabled in test config') # Make 10 successful submissions (the limit) for i in range(10): data = {'feedback_text': f'Feedback {i}'} response = client.post('/submit/test-product', data=data) # Should succeed (200 or 302) assert response.status_code in [200, 302] # 11th submission should be rate limited data = {'feedback_text': 'This should be rate limited'} response = client.post('/submit/test-product', data=data) assert response.status_code == 429