8
8
from scrapy .contracts import Contract , ContractsManager
9
9
from scrapy .contracts .default import (
10
10
CallbackKeywordArgumentsContract ,
11
+ MetadataContract ,
11
12
ReturnsContract ,
12
13
ScrapesContract ,
13
14
UrlContract ,
@@ -29,6 +30,10 @@ class ResponseMock:
29
30
url = "http://scrapy.org"
30
31
31
32
33
+ class ResponseMetaMock (ResponseMock ):
34
+ meta = None
35
+
36
+
32
37
class CustomSuccessContract (Contract ):
33
38
name = "custom_success_contract"
34
39
@@ -195,6 +200,33 @@ def invalid_regex_with_valid_contract(self, response):
195
200
"""
196
201
pass
197
202
203
+ def returns_request_meta (self , response ):
204
+ """method which returns request
205
+ @url https://example.org
206
+ @meta {"cookiejar": "session1"}
207
+ @returns requests 1
208
+ """
209
+ return Request (
210
+ "https://example.org" , meta = response .meta , callback = self .returns_item_meta
211
+ )
212
+
213
+ def returns_item_meta (self , response ):
214
+ """method which returns item
215
+ @url http://scrapy.org
216
+ @meta {"key": "example"}
217
+ @returns items 1 1
218
+ """
219
+ return TestItem (name = "example" , url = response .url )
220
+
221
+ def returns_error_missing_meta (self , response ):
222
+ """method which depends of metadata be defined
223
+
224
+ @url http://scrapy.org
225
+ @returns items 1
226
+ """
227
+ key = response .meta ["key" ]
228
+ yield {key : "value" }
229
+
198
230
199
231
class CustomContractSuccessSpider (Spider ):
200
232
name = "custom_contract_success_spider"
@@ -224,6 +256,7 @@ class ContractsManagerTest(unittest.TestCase):
224
256
contracts = [
225
257
UrlContract ,
226
258
CallbackKeywordArgumentsContract ,
259
+ MetadataContract ,
227
260
ReturnsContract ,
228
261
ScrapesContract ,
229
262
CustomFormContract ,
@@ -328,6 +361,52 @@ def test_cb_kwargs(self):
328
361
request .callback (response , ** request .cb_kwargs )
329
362
self .should_error ()
330
363
364
+ def test_meta (self ):
365
+ spider = TestSpider ()
366
+
367
+ # extract contracts correctly
368
+ contracts = self .conman .extract_contracts (spider .returns_request_meta )
369
+ self .assertEqual (len (contracts ), 3 )
370
+ self .assertEqual (
371
+ frozenset (type (x ) for x in contracts ),
372
+ frozenset ([UrlContract , MetadataContract , ReturnsContract ]),
373
+ )
374
+
375
+ contracts = self .conman .extract_contracts (spider .returns_item_meta )
376
+ self .assertEqual (len (contracts ), 3 )
377
+ self .assertEqual (
378
+ frozenset (type (x ) for x in contracts ),
379
+ frozenset ([UrlContract , MetadataContract , ReturnsContract ]),
380
+ )
381
+
382
+ response = ResponseMetaMock ()
383
+
384
+ # returns_request
385
+ request = self .conman .from_method (spider .returns_request_meta , self .results )
386
+ assert request .meta ["cookiejar" ] == "session1"
387
+ response .meta = request .meta
388
+ request .callback (response )
389
+ assert response .meta ["cookiejar" ] == "session1"
390
+ self .should_succeed ()
391
+
392
+ response = ResponseMetaMock ()
393
+
394
+ # returns_item
395
+ request = self .conman .from_method (spider .returns_item_meta , self .results )
396
+ assert request .meta ["key" ] == "example"
397
+ response .meta = request .meta
398
+ request .callback (ResponseMetaMock )
399
+ assert response .meta ["key" ] == "example"
400
+ self .should_succeed ()
401
+
402
+ response = ResponseMetaMock ()
403
+
404
+ request = self .conman .from_method (
405
+ spider .returns_error_missing_meta , self .results
406
+ )
407
+ request .callback (response )
408
+ self .should_error ()
409
+
331
410
def test_returns (self ):
332
411
spider = TestSpider ()
333
412
response = ResponseMock ()
0 commit comments