0
# Accept Headers
1
2
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.
3
4
## Capabilities
5
6
### JSON Accept Header
7
8
Accept header specifically configured for JSON content type, commonly used for API testing.
9
10
```python { .api }
11
@pytest.fixture
12
def accept_json(request):
13
"""
14
Accept header for JSON content type.
15
16
Returns:
17
list: [("Accept", "application/json")]
18
"""
19
```
20
21
**Usage Example:**
22
23
```python
24
def test_json_api_endpoint(client, accept_json):
25
"""Test API endpoint that returns JSON"""
26
response = client.get('/api/users', headers=accept_json)
27
assert response.status_code == 200
28
assert response.content_type == 'application/json'
29
assert isinstance(response.json, list)
30
31
def test_content_negotiation_json(client, accept_json):
32
"""Test content negotiation preferring JSON"""
33
response = client.get('/api/data', headers=accept_json)
34
assert response.status_code == 200
35
assert 'application/json' in response.content_type
36
37
# Verify JSON structure
38
data = response.json
39
assert 'items' in data
40
assert 'total' in data
41
```
42
43
### JSONP Accept Header
44
45
Accept header configured for JSONP (JSON with Padding) content type, used for cross-domain requests.
46
47
```python { .api }
48
@pytest.fixture
49
def accept_jsonp():
50
"""
51
Accept header for JSONP content type.
52
53
Returns:
54
list: [("Accept", "application/json-p")]
55
"""
56
```
57
58
**Usage Example:**
59
60
```python
61
def test_jsonp_endpoint(client, accept_jsonp):
62
"""Test JSONP endpoint for cross-domain requests"""
63
response = client.get('/api/jsonp-data',
64
headers=accept_jsonp,
65
query_string={'callback': 'myCallback'})
66
assert response.status_code == 200
67
assert response.content_type == 'application/json-p'
68
assert response.data.decode().startswith('myCallback(')
69
70
def test_jsonp_callback_handling(client, accept_jsonp):
71
"""Test JSONP callback parameter handling"""
72
callback_name = 'processData'
73
response = client.get('/api/stats',
74
headers=accept_jsonp,
75
query_string={'callback': callback_name})
76
assert response.status_code == 200
77
content = response.data.decode()
78
assert content.startswith(f'{callback_name}(')
79
assert content.endswith(');')
80
```
81
82
### Parametrized MIME Type Headers
83
84
Parametrized fixture that tests multiple common MIME types, useful for testing content negotiation across different formats.
85
86
```python { .api }
87
@pytest.fixture(params=["application/json", "text/html"])
88
def accept_mimetype(request):
89
"""
90
Parametrized fixture for common MIME types.
91
92
Parameters:
93
request.param: One of "application/json" or "text/html"
94
95
Returns:
96
list: [("Accept", mimetype)] for each parameter
97
"""
98
```
99
100
**Usage Example:**
101
102
```python
103
def test_content_negotiation(client, accept_mimetype):
104
"""Test endpoint supports multiple content types"""
105
response = client.get('/api/flexible-endpoint', headers=accept_mimetype)
106
assert response.status_code == 200
107
108
# Check response matches requested content type
109
if accept_mimetype == [("Accept", "application/json")]:
110
assert 'application/json' in response.content_type
111
assert response.json is not None
112
elif accept_mimetype == [("Accept", "text/html")]:
113
assert 'text/html' in response.content_type
114
assert '<html>' in response.data.decode()
115
116
def test_api_format_support(client, accept_mimetype):
117
"""Test API supports both JSON and HTML responses"""
118
response = client.get('/api/users/123', headers=accept_mimetype)
119
assert response.status_code == 200
120
121
content_type = response.content_type
122
if 'json' in content_type:
123
user_data = response.json
124
assert 'id' in user_data
125
assert 'name' in user_data
126
elif 'html' in content_type:
127
html_content = response.data.decode()
128
assert 'User Profile' in html_content
129
assert 'id="user-123"' in html_content
130
```
131
132
### Wildcard Accept Headers
133
134
Parametrized fixture for wildcard accept headers, testing endpoints that accept any content type.
135
136
```python { .api }
137
@pytest.fixture(params=["*", "*/*"])
138
def accept_any(request):
139
"""
140
Accept header for any content type.
141
142
Parameters:
143
request.param: One of "*" or "*/*"
144
145
Returns:
146
list: [("Accept", wildcard_type)] for each parameter
147
"""
148
```
149
150
**Usage Example:**
151
152
```python
153
def test_accepts_any_content(client, accept_any):
154
"""Test endpoint accepts any content type"""
155
response = client.get('/api/flexible', headers=accept_any)
156
assert response.status_code == 200
157
# Endpoint should respond with its default content type
158
assert response.content_type is not None
159
160
def test_default_content_type(client, accept_any):
161
"""Test default content type when accepting anything"""
162
response = client.get('/api/data', headers=accept_any)
163
assert response.status_code == 200
164
165
# Should default to JSON for API endpoints
166
assert 'application/json' in response.content_type
167
assert response.json is not None
168
169
def test_proxy_requests(client, accept_any):
170
"""Test proxy endpoint that passes through various content types"""
171
# Test with different upstream content types
172
response = client.get('/proxy/external-api', headers=accept_any)
173
assert response.status_code in [200, 304] # Success or not modified
174
```
175
176
## Advanced Usage
177
178
### Custom Accept Headers
179
180
Combine fixtures for complex content negotiation testing:
181
182
```python
183
def test_multiple_accept_types(client):
184
"""Test with multiple accept types in priority order"""
185
headers = [
186
("Accept", "application/json"),
187
("Accept", "application/xml"),
188
("Accept", "text/html")
189
]
190
response = client.get('/api/content-negotiation', headers=headers)
191
assert response.status_code == 200
192
# Should return highest priority supported type
193
194
def test_quality_values(client):
195
"""Test Accept header with quality values"""
196
headers = [("Accept", "application/json;q=0.9, text/html;q=0.8")]
197
response = client.get('/api/data', headers=headers)
198
assert response.status_code == 200
199
# Should prefer JSON due to higher quality value
200
assert 'application/json' in response.content_type
201
```
202
203
### Combined with Other Fixtures
204
205
Use accept header fixtures with other pytest-flask fixtures:
206
207
```python
208
@pytest.mark.options(api_version='v2')
209
def test_versioned_api_json(client, accept_json, config):
210
"""Test versioned API with JSON response"""
211
headers = accept_json + [("API-Version", config['API_VERSION'])]
212
response = client.get('/api/users', headers=headers)
213
assert response.status_code == 200
214
assert response.json['version'] == 'v2'
215
216
def test_live_server_content_negotiation(live_server, accept_json):
217
"""Test content negotiation with live server"""
218
import requests
219
220
headers = dict(accept_json)
221
response = requests.get(
222
live_server.url('/api/external'),
223
headers=headers
224
)
225
assert response.status_code == 200
226
assert response.headers['content-type'] == 'application/json'
227
```
228
229
### Testing Content Negotiation Errors
230
231
Test how applications handle unsupported content types:
232
233
```python
234
def test_unsupported_content_type(client):
235
"""Test response to unsupported Accept header"""
236
headers = [("Accept", "application/xml")]
237
response = client.get('/api/json-only', headers=headers)
238
# Should return 406 Not Acceptable or fallback to default
239
assert response.status_code in [200, 406]
240
241
if response.status_code == 406:
242
assert 'Not Acceptable' in response.data.decode()
243
else:
244
# Fallback to default JSON
245
assert 'application/json' in response.content_type
246
```