CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pytest-flask

A set of pytest fixtures to test Flask applications.

Pending
Overview
Eval results
Files

accept-headers.mddocs/

Accept Headers

Pre-configured HTTP Accept header fixtures for testing content negotiation and API responses. Provides standardized header configurations for common MIME types and content negotiation scenarios.

Capabilities

JSON Accept Header

Accept header specifically configured for JSON content type, commonly used for API testing.

@pytest.fixture
def accept_json(request):
    """
    Accept header for JSON content type.
    
    Returns:
        list: [("Accept", "application/json")]
    """

Usage Example:

def test_json_api_endpoint(client, accept_json):
    """Test API endpoint that returns JSON"""
    response = client.get('/api/users', headers=accept_json)
    assert response.status_code == 200
    assert response.content_type == 'application/json'
    assert isinstance(response.json, list)

def test_content_negotiation_json(client, accept_json):
    """Test content negotiation preferring JSON"""
    response = client.get('/api/data', headers=accept_json)
    assert response.status_code == 200
    assert 'application/json' in response.content_type
    
    # Verify JSON structure
    data = response.json
    assert 'items' in data
    assert 'total' in data

JSONP Accept Header

Accept header configured for JSONP (JSON with Padding) content type, used for cross-domain requests.

@pytest.fixture
def accept_jsonp():
    """
    Accept header for JSONP content type.
    
    Returns:
        list: [("Accept", "application/json-p")]
    """

Usage Example:

def test_jsonp_endpoint(client, accept_jsonp):
    """Test JSONP endpoint for cross-domain requests"""
    response = client.get('/api/jsonp-data', 
                         headers=accept_jsonp,
                         query_string={'callback': 'myCallback'})
    assert response.status_code == 200
    assert response.content_type == 'application/json-p'
    assert response.data.decode().startswith('myCallback(')

def test_jsonp_callback_handling(client, accept_jsonp):
    """Test JSONP callback parameter handling"""
    callback_name = 'processData'
    response = client.get('/api/stats',
                         headers=accept_jsonp,
                         query_string={'callback': callback_name})
    assert response.status_code == 200
    content = response.data.decode()
    assert content.startswith(f'{callback_name}(')
    assert content.endswith(');')

Parametrized MIME Type Headers

Parametrized fixture that tests multiple common MIME types, useful for testing content negotiation across different formats.

@pytest.fixture(params=["application/json", "text/html"])
def accept_mimetype(request):
    """
    Parametrized fixture for common MIME types.
    
    Parameters:
        request.param: One of "application/json" or "text/html"
        
    Returns:
        list: [("Accept", mimetype)] for each parameter
    """

Usage Example:

def test_content_negotiation(client, accept_mimetype):
    """Test endpoint supports multiple content types"""
    response = client.get('/api/flexible-endpoint', headers=accept_mimetype)
    assert response.status_code == 200
    
    # Check response matches requested content type
    if accept_mimetype == [("Accept", "application/json")]:
        assert 'application/json' in response.content_type
        assert response.json is not None
    elif accept_mimetype == [("Accept", "text/html")]:
        assert 'text/html' in response.content_type
        assert '<html>' in response.data.decode()

def test_api_format_support(client, accept_mimetype):
    """Test API supports both JSON and HTML responses"""
    response = client.get('/api/users/123', headers=accept_mimetype)
    assert response.status_code == 200
    
    content_type = response.content_type
    if 'json' in content_type:
        user_data = response.json
        assert 'id' in user_data
        assert 'name' in user_data
    elif 'html' in content_type:
        html_content = response.data.decode()
        assert 'User Profile' in html_content
        assert 'id="user-123"' in html_content

Wildcard Accept Headers

Parametrized fixture for wildcard accept headers, testing endpoints that accept any content type.

@pytest.fixture(params=["*", "*/*"])
def accept_any(request):
    """
    Accept header for any content type.
    
    Parameters:
        request.param: One of "*" or "*/*"
        
    Returns:
        list: [("Accept", wildcard_type)] for each parameter
    """

Usage Example:

def test_accepts_any_content(client, accept_any):
    """Test endpoint accepts any content type"""
    response = client.get('/api/flexible', headers=accept_any)
    assert response.status_code == 200
    # Endpoint should respond with its default content type
    assert response.content_type is not None

def test_default_content_type(client, accept_any):
    """Test default content type when accepting anything"""
    response = client.get('/api/data', headers=accept_any)
    assert response.status_code == 200
    
    # Should default to JSON for API endpoints
    assert 'application/json' in response.content_type
    assert response.json is not None

def test_proxy_requests(client, accept_any):
    """Test proxy endpoint that passes through various content types"""
    # Test with different upstream content types
    response = client.get('/proxy/external-api', headers=accept_any)
    assert response.status_code in [200, 304]  # Success or not modified

Advanced Usage

Custom Accept Headers

Combine fixtures for complex content negotiation testing:

def test_multiple_accept_types(client):
    """Test with multiple accept types in priority order"""
    headers = [
        ("Accept", "application/json"),
        ("Accept", "application/xml"),
        ("Accept", "text/html")
    ]
    response = client.get('/api/content-negotiation', headers=headers)
    assert response.status_code == 200
    # Should return highest priority supported type

def test_quality_values(client):
    """Test Accept header with quality values"""
    headers = [("Accept", "application/json;q=0.9, text/html;q=0.8")]
    response = client.get('/api/data', headers=headers)
    assert response.status_code == 200
    # Should prefer JSON due to higher quality value
    assert 'application/json' in response.content_type

Combined with Other Fixtures

Use accept header fixtures with other pytest-flask fixtures:

@pytest.mark.options(api_version='v2')
def test_versioned_api_json(client, accept_json, config):
    """Test versioned API with JSON response"""
    headers = accept_json + [("API-Version", config['API_VERSION'])]
    response = client.get('/api/users', headers=headers)
    assert response.status_code == 200
    assert response.json['version'] == 'v2'

def test_live_server_content_negotiation(live_server, accept_json):
    """Test content negotiation with live server"""
    import requests
    
    headers = dict(accept_json)
    response = requests.get(
        live_server.url('/api/external'), 
        headers=headers
    )
    assert response.status_code == 200
    assert response.headers['content-type'] == 'application/json'

Testing Content Negotiation Errors

Test how applications handle unsupported content types:

def test_unsupported_content_type(client):
    """Test response to unsupported Accept header"""
    headers = [("Accept", "application/xml")]
    response = client.get('/api/json-only', headers=headers)
    # Should return 406 Not Acceptable or fallback to default
    assert response.status_code in [200, 406]
    
    if response.status_code == 406:
        assert 'Not Acceptable' in response.data.decode()
    else:
        # Fallback to default JSON
        assert 'application/json' in response.content_type

Install with Tessl CLI

npx tessl i tessl/pypi-pytest-flask

docs

accept-headers.md

configuration.md

index.md

live-server.md

test-client.md

tile.json