mirror of https://github.com/scrapy/scrapy.git
Merge pull request #3383 from StasDeep/feature/issue-3382
[MRG+1] Add ability to use FormRequest in contracts
This commit is contained in:
commit
ae8a0dc77c
|
|
@ -86,8 +86,11 @@ override three methods:
|
|||
.. method:: Contract.adjust_request_args(args)
|
||||
|
||||
This receives a ``dict`` as an argument containing default arguments
|
||||
for :class:`~scrapy.http.Request` object. Must return the same or a
|
||||
modified version of it.
|
||||
for request object. :class:`~scrapy.http.Request` is used by default,
|
||||
but this can be changed with the ``request_cls`` attribute.
|
||||
If multiple contracts in chain have this attribute defined, the last one is used.
|
||||
|
||||
Must return the same or a modified version of it.
|
||||
|
||||
.. method:: Contract.pre_process(response)
|
||||
|
||||
|
|
|
|||
|
|
@ -49,16 +49,22 @@ class ContractsManager(object):
|
|||
def from_method(self, method, results):
|
||||
contracts = self.extract_contracts(method)
|
||||
if contracts:
|
||||
request_cls = Request
|
||||
for contract in contracts:
|
||||
if contract.request_cls is not None:
|
||||
request_cls = contract.request_cls
|
||||
|
||||
# calculate request args
|
||||
args, kwargs = get_spec(Request.__init__)
|
||||
args, kwargs = get_spec(request_cls.__init__)
|
||||
kwargs['callback'] = method
|
||||
for contract in contracts:
|
||||
kwargs = contract.adjust_request_args(kwargs)
|
||||
|
||||
# create and prepare request
|
||||
args.remove('self')
|
||||
|
||||
# check if all positional arguments are defined in kwargs
|
||||
if set(args).issubset(set(kwargs)):
|
||||
request = Request(**kwargs)
|
||||
request = request_cls(**kwargs)
|
||||
|
||||
# execute pre and post hooks in order
|
||||
for contract in reversed(contracts):
|
||||
|
|
@ -94,6 +100,7 @@ class ContractsManager(object):
|
|||
|
||||
class Contract(object):
|
||||
""" Abstract class for contracts """
|
||||
request_cls = None
|
||||
|
||||
def __init__(self, method, *args):
|
||||
self.testcase_pre = _create_testcase(method, '@%s pre-hook' % self.name)
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ from unittest import TextTestResult
|
|||
from twisted.python import failure
|
||||
from twisted.trial import unittest
|
||||
|
||||
from scrapy import FormRequest
|
||||
from scrapy.spidermiddlewares.httperror import HttpError
|
||||
from scrapy.spiders import Spider
|
||||
from scrapy.http import Request
|
||||
from scrapy.item import Item, Field
|
||||
from scrapy.contracts import ContractsManager
|
||||
from scrapy.contracts import ContractsManager, Contract
|
||||
from scrapy.contracts.default import (
|
||||
UrlContract,
|
||||
ReturnsContract,
|
||||
|
|
@ -24,6 +25,15 @@ class ResponseMock(object):
|
|||
url = 'http://scrapy.org'
|
||||
|
||||
|
||||
class CustomFormContract(Contract):
|
||||
name = 'custom_form'
|
||||
request_cls = FormRequest
|
||||
|
||||
def adjust_request_args(self, args):
|
||||
args['formdata'] = {'name': 'scrapy'}
|
||||
return args
|
||||
|
||||
|
||||
class TestSpider(Spider):
|
||||
name = 'demo_spider'
|
||||
|
||||
|
|
@ -100,13 +110,20 @@ class TestSpider(Spider):
|
|||
"""
|
||||
pass
|
||||
|
||||
def custom_form(self, response):
|
||||
"""
|
||||
@url http://scrapy.org
|
||||
@custom_form
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class InheritsTestSpider(TestSpider):
|
||||
name = 'inherits_demo_spider'
|
||||
|
||||
|
||||
class ContractsManagerTest(unittest.TestCase):
|
||||
contracts = [UrlContract, ReturnsContract, ScrapesContract]
|
||||
contracts = [UrlContract, ReturnsContract, ScrapesContract, CustomFormContract]
|
||||
|
||||
def setUp(self):
|
||||
self.conman = ContractsManager(self.contracts)
|
||||
|
|
@ -207,6 +224,12 @@ class ContractsManagerTest(unittest.TestCase):
|
|||
self.assertFalse(self.results.failures)
|
||||
self.assertTrue(self.results.errors)
|
||||
|
||||
def test_form_contract(self):
|
||||
spider = TestSpider()
|
||||
request = self.conman.from_method(spider.custom_form, self.results)
|
||||
self.assertEqual(request.method, 'POST')
|
||||
self.assertIsInstance(request, FormRequest)
|
||||
|
||||
def test_inherited_contracts(self):
|
||||
spider = InheritsTestSpider()
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue