class TestVhostWebserviceFactory(WebServiceTestCase): class VHostTestBrowserRequest(LaunchpadBrowserRequest): pass class VHostTestPublication(LaunchpadBrowserRequest): pass def setUp(self): super(TestVhostWebserviceFactory, self).setUp() # XXX We have to use a real hostname. self.factory = VHostWebServiceRequestPublicationFactory( 'bugs', self.VHostTestBrowserRequest, self.VHostTestPublication) def wsgi_env(self, path, method='GET'): """Simulate a WSGI application environment.""" return { 'PATH_INFO': path, 'HTTP_HOST': 'bugs.launchpad.dev', 'REQUEST_METHOD': method, } @property def api_path(self): """Requests to this path should be treated as webservice requests.""" return '/' + getUtility(IWebServiceConfiguration).path_override @property def non_api_path(self): """Requests to this path should not be treated as webservice requests. """ return '/foo' def test_factory_produces_webservice_objects(self): """The factory should produce WebService request and publication objects for requests to the /api root URL. """ env = self.wsgi_env(self.api_path) # Necessary preamble and sanity check. We need to call # the factory's canHandle() method with an appropriate # WSGI environment before it can produce a request object for us. self.assert_( self.factory.canHandle(env), "Sanity check: The factory should be able to handle requests.") wrapped_factory, publication_factory = self.factory() # We need to unwrap the real request factory. request_factory = wrapped_factory.requestfactory self.assertEqual( request_factory, WebServiceClientRequest, "Requests to the /api path should return a WebService " "request object.") self.assertEqual( publication_factory, WebServicePublication, "Requests to the /api path should return a WebService " "publication object.") def test_factory_produces_normal_request_objects(self): """The factory should return the request and publication factories specified in it's constructor if the request is not bound for the web service. """ env = self.wsgi_env(self.non_api_path) self.assert_( self.factory.canHandle(env), "Sanity check: The factory should be able to handle requests.") wrapped_factory, publication_factory = self.factory() # We need to unwrap the real request factory. request_factory = wrapped_factory.requestfactory self.assertEqual( request_factory, self.VHostTestBrowserRequest, "Requests to normal paths should return a VHostTest " "request object.") self.assertEqual( publication_factory, self.VHostTestPublication, "Requests to normal paths should return a VHostTest " "publication object.") def test_factory_processes_webservice_http_methods(self): """The factory should accept the HTTP methods for requests that should be processed by the web service. """ allowed_methods = WebServiceRequestPublicationFactory.default_methods for method in allowed_methods: env = self.wsgi_env(self.api_path, method) self.assert_(self.factory.canHandle(env), "Sanity check") # Returns a tuple of (request_factory, publication_factory). rfactory, pfactory = self.factory.checkRequest(env) self.assert_( rfactory is None, "The '%s' HTTP method should be handled by the factory." % method) def test_factory_rejects_normal_http_methods(self): """The factory should reject some HTTP methods for requests that are *not* bound for the web service. This includes methods like 'PUT' and 'PATCH'. """ vhost_methods = VirtualHostRequestPublicationFactory.default_methods ws_methods = WebServiceRequestPublicationFactory.default_methods denied_methods = set(ws_methods) - set(vhost_methods) for method in denied_methods: env = self.wsgi_env(self.non_api_path, method) self.assert_(self.factory.canHandle(env), "Sanity check") # Returns a tuple of (request_factory, publication_factory). rfactory, pfactory = self.factory.checkRequest(env) self.assert_( rfactory is not None, "The '%s' HTTP method should be rejected by the factory." % method) def test_factory_understands_webservice_paths(self): """The factory should know if a path is directed at a web service resource path. """ # This is a sanity check, so I can write '/api/foo' instead # of PATH_OVERRIDE + '/foo' in my tests. The former's # intention is clearer. self.assertEqual( getUtility(IWebServiceConfiguration).path_override, 'api', "Sanity check: The web service path override should be 'api'.") self.assert_(self.factory.isWebServicePath('/api'), "The factory should handle URLs that start with /api.") self.assert_(self.factory.isWebServicePath('/api/foo'), "The factory should handle URLs that start with /api.") self.failIf( self.factory.isWebServicePath('/foo'), "The factory should not handle URLs that do not start with " "/api.") self.failIf( self.factory.isWebServicePath('/'), "The factory should not handle URLs that do not start with " "/api.") self.failIf( self.factory.isWebServicePath('/apifoo'), "The factory should not handle URLs that do not start with " "/api.") self.failIf( self.factory.isWebServicePath('/foo/api'), "The factory should not handle URLs that do not start with " "/api.")
def setUp(self): super(TestVhostWebserviceFactory, self).setUp() # XXX We have to use a real hostname. self.factory = VHostWebServiceRequestPublicationFactory( 'bugs', self.VHostTestBrowserRequest, self.VHostTestPublication)
def code_request_publication_factory(): return VHostWebServiceRequestPublicationFactory( 'code', CodeBrowserRequest, LaunchpadBrowserPublication)
def bugs_request_publication_factory(): return VHostWebServiceRequestPublicationFactory( 'bugs', BugsBrowserRequest, LaunchpadBrowserPublication)
def translations_request_publication_factory(): return VHostWebServiceRequestPublicationFactory( 'translations', TranslationsBrowserRequest, LaunchpadBrowserPublication)
def answers_request_publication_factory(): return VHostWebServiceRequestPublicationFactory( 'answers', AnswersBrowserRequest, LaunchpadBrowserPublication)
def blueprints_request_publication_factory(): return VHostWebServiceRequestPublicationFactory( 'blueprints', BlueprintsBrowserRequest, LaunchpadBrowserPublication)
class TestVhostWebserviceFactory(WebServiceTestCase): class VHostTestBrowserRequest(LaunchpadBrowserRequest): pass class VHostTestPublication(LaunchpadBrowserRequest): pass def setUp(self): super(TestVhostWebserviceFactory, self).setUp() # XXX We have to use a real hostname. self.factory = VHostWebServiceRequestPublicationFactory( 'bugs', self.VHostTestBrowserRequest, self.VHostTestPublication) def wsgi_env(self, path, method='GET'): """Simulate a WSGI application environment.""" return { 'PATH_INFO': path, 'HTTP_HOST': 'bugs.launchpad.dev', 'REQUEST_METHOD': method, } @property def api_path(self): """Requests to this path should be treated as webservice requests.""" return '/' + getUtility(IWebServiceConfiguration).path_override @property def non_api_path(self): """Requests to this path should not be treated as webservice requests. """ return '/foo' def test_factory_produces_webservice_objects(self): """The factory should produce WebService request and publication objects for requests to the /api root URL. """ env = self.wsgi_env(self.api_path) # Necessary preamble and sanity check. We need to call # the factory's canHandle() method with an appropriate # WSGI environment before it can produce a request object for us. self.assert_(self.factory.canHandle(env), "Sanity check: The factory should be able to handle requests.") wrapped_factory, publication_factory = self.factory() # We need to unwrap the real request factory. request_factory = wrapped_factory.requestfactory self.assertEqual(request_factory, WebServiceClientRequest, "Requests to the /api path should return a WebService " "request object.") self.assertEqual( publication_factory, WebServicePublication, "Requests to the /api path should return a WebService " "publication object.") def test_factory_produces_normal_request_objects(self): """The factory should return the request and publication factories specified in it's constructor if the request is not bound for the web service. """ env = self.wsgi_env(self.non_api_path) self.assert_(self.factory.canHandle(env), "Sanity check: The factory should be able to handle requests.") wrapped_factory, publication_factory = self.factory() # We need to unwrap the real request factory. request_factory = wrapped_factory.requestfactory self.assertEqual(request_factory, self.VHostTestBrowserRequest, "Requests to normal paths should return a VHostTest " "request object.") self.assertEqual( publication_factory, self.VHostTestPublication, "Requests to normal paths should return a VHostTest " "publication object.") def test_factory_processes_webservice_http_methods(self): """The factory should accept the HTTP methods for requests that should be processed by the web service. """ allowed_methods = WebServiceRequestPublicationFactory.default_methods for method in allowed_methods: env = self.wsgi_env(self.api_path, method) self.assert_(self.factory.canHandle(env), "Sanity check") # Returns a tuple of (request_factory, publication_factory). rfactory, pfactory = self.factory.checkRequest(env) self.assert_(rfactory is None, "The '%s' HTTP method should be handled by the factory." % method) def test_factory_rejects_normal_http_methods(self): """The factory should reject some HTTP methods for requests that are *not* bound for the web service. This includes methods like 'PUT' and 'PATCH'. """ vhost_methods = VirtualHostRequestPublicationFactory.default_methods ws_methods = WebServiceRequestPublicationFactory.default_methods denied_methods = set(ws_methods) - set(vhost_methods) for method in denied_methods: env = self.wsgi_env(self.non_api_path, method) self.assert_(self.factory.canHandle(env), "Sanity check") # Returns a tuple of (request_factory, publication_factory). rfactory, pfactory = self.factory.checkRequest(env) self.assert_(rfactory is not None, "The '%s' HTTP method should be rejected by the factory." % method) def test_factory_understands_webservice_paths(self): """The factory should know if a path is directed at a web service resource path. """ # This is a sanity check, so I can write '/api/foo' instead # of PATH_OVERRIDE + '/foo' in my tests. The former's # intention is clearer. self.assertEqual( getUtility(IWebServiceConfiguration).path_override, 'api', "Sanity check: The web service path override should be 'api'.") self.assert_( self.factory.isWebServicePath('/api'), "The factory should handle URLs that start with /api.") self.assert_( self.factory.isWebServicePath('/api/foo'), "The factory should handle URLs that start with /api.") self.failIf( self.factory.isWebServicePath('/foo'), "The factory should not handle URLs that do not start with " "/api.") self.failIf( self.factory.isWebServicePath('/'), "The factory should not handle URLs that do not start with " "/api.") self.failIf( self.factory.isWebServicePath('/apifoo'), "The factory should not handle URLs that do not start with " "/api.") self.failIf( self.factory.isWebServicePath('/foo/api'), "The factory should not handle URLs that do not start with " "/api.")