From 19f2be8e32cb3ab9534a4d66685665c7db6e00ce Mon Sep 17 00:00:00 2001 From: amercader Date: Thu, 25 Aug 2016 13:38:05 +0100 Subject: [PATCH 01/71] [#3196] Provide the necessary environment for routers to work Although each app has its own routing mechanism (Flask and Pylons (routes)), we still need to be able to generate a URL that is served by the other application. For instance, when requesting `/dataset`, which is currently served by Pylons, we call `h.url_for(controller='api', action='get_api')`. This endpoint is served by Flask, so Pylons won't know how to generate the URL. We need a wrapper that tries Flask first and falls back to Pylons (next commit). In order to do that though, the mappers need to work even if the request is not served by their app. For Flask routes under requests served by Pylons, we wrap the response in a `test_request_context`. We don't use an `app_context` because this causes the following errors: RuntimeError: Application was not able to create a URL adapter for request independent URL generation. For Pylons routes under requests served by Flask, we set the Routes configuration directly. --- ckan/config/middleware/__init__.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ckan/config/middleware/__init__.py b/ckan/config/middleware/__init__.py index 41e58cc3840..c1270e24bc6 100644 --- a/ckan/config/middleware/__init__.py +++ b/ckan/config/middleware/__init__.py @@ -1,14 +1,16 @@ # encoding: utf-8 """WSGI app initialization""" +import urlparse import webob -from werkzeug.test import create_environ, run_wsgi_app +from routes import request_config as routes_request_config from ckan.config.environment import load_environment from ckan.config.middleware.flask_app import make_flask_stack from ckan.config.middleware.pylons_app import make_pylons_stack +from ckan.common import config import logging log = logging.getLogger(__name__) @@ -124,6 +126,15 @@ def __call__(self, environ, start_response): log.debug('Serving request via {0} app'.format(app_name)) environ['ckan.app'] = app_name if app_name == 'flask_app': + # This request will be served by Flask, but we still need the + # Pylons URL builder (Routes) to work + parts = urlparse.urlparse(config.get('ckan.site_url', + 'http://0.0.0.0:5000')) + request_config = routes_request_config() + request_config.host = str(parts.netloc + parts.path) + request_config.protocol = str(parts.scheme) + request_config.mapper = config['routes.map'] + return self.apps[app_name](environ, start_response) else: # Although this request will be served by Pylons we still @@ -131,5 +142,5 @@ def __call__(self, environ, start_response): # builder to work and to be able to access the Flask config flask_app = self.apps['flask_app']._wsgi_app - with flask_app.app_context(): + with flask_app.test_request_context(): return self.apps[app_name](environ, start_response) From b5ea2e7ffa312534017275337c3d709d3a0a5e7b Mon Sep 17 00:00:00 2001 From: amercader Date: Thu, 25 Aug 2016 13:47:46 +0100 Subject: [PATCH 02/71] [#3196] New version of url_for to supports both Flask and Pylons Essentially this calls the Flask url_for function and falls back to Pylons if a route could not be created. There's a lot of parameters handling before calling the Flask router to support Pylons syntax (at least the most common cases): # Pylons url = url_for(controller='api', action='action', ver=3, qualified=True) # Flask url = url_for('api.action', ver=3, _external=True) We don't rely on the host generated by Flask, as SERVER_NAME might not be set or might be not be up to date (as in tests changing `ckan.site_url`). Contrary to the Routes mapper, there is no way in Flask to pass the host explicitly, so we rebuild the URL manually based on `ckan.site_url`, which is essentially what we alredy do on Pylons. I experimented with automatically set SERVER_NAME based on `ckan.site_url`, but decided against it. Apart from being magic that we want to avoid, the main cause of concern of doing this is that when SERVER_NAME is set, the Flask router requires the incoming URL (HTTP_HOST on environ) to have the same host as the one defined in SERVER_NAME, otherwise it won't match the URL and return a 404. For example if ckan.site_url is set to http://localhost:5000 (so SERVER_NAME is localhost:5000), calls to http://127.0.0.1:5000 or http://0.0.0.0:5000 won't work. This would cause massive confusion to users, specially during development or early deployment stages, so it's best to avoid it. --- ckan/lib/helpers.py | 149 ++++++++++++++++++++++++--- ckan/tests/config/test_middleware.py | 22 +++- ckan/tests/lib/test_helpers.py | 127 +++++++++++++++++++++-- 3 files changed, 274 insertions(+), 24 deletions(-) diff --git a/ckan/lib/helpers.py b/ckan/lib/helpers.py index 5d6f6d2d646..d3d31427214 100644 --- a/ckan/lib/helpers.py +++ b/ckan/lib/helpers.py @@ -30,6 +30,8 @@ from flask import redirect as _flask_redirect from routes import redirect_to as _routes_redirect_to from routes import url_for as _routes_default_url_for +from flask import url_for as _flask_default_url_for +from werkzeug.routing import BuildError as FlaskRouteBuildError import i18n import ckan.exceptions @@ -191,43 +193,156 @@ def get_site_protocol_and_host(): @core_helper def url_for(*args, **kw): - '''Return the URL for the given controller, action, id, etc. + '''Return the URL for an endpoint given some parameters. - Usage:: + This is a wrapper for :py:func:`flask.url_for` + and :py:func:`routes.url_for` that adds some extra features that CKAN + needs. - import ckan.plugins.toolkit as toolkit + To build a URL for a Flask view, pass the name of the blueprint and the + view function separated by a period ``.``, plus any URL parameters:: + + url_for('api.action', ver=3, logic_function='status_show') + # Returns /api/3/action/status_show + + For a fully qualified URL pass the ``_external=True`` parameter. This + takes the ``ckan.site_url`` and ``ckan.root_path`` settings into account:: + + url_for('api.action', ver=3, logic_function='status_show', + _external=True) + # Returns http://example.com/api/3/action/status_show + + URLs built by Pylons use the Routes syntax:: - url = toolkit.url_for(controller='package', action='read', - id='my_dataset') - => returns '/dataset/my_dataset' + url_for(controller='package', action='read', id='my_dataset') + # Returns '/dataset/my_dataset' Or, using a named route:: - toolkit.url_for('dataset_read', id='changed') + url_for('dataset_read', id='changed') + # Returns '/dataset/changed' - This is a wrapper for :py:func:`routes.url_for` that adds some extra - features that CKAN needs. + Use ``qualified=True`` for a fully qualified URL when targeting a Pylons + endpoint. + For backwards compatibility, an effort is made to support the Pylons syntax + when building a Flask URL, but this support might be dropped in the future, + so calls should be updated. ''' + # Get the actual string code for the locale locale = kw.pop('locale', None) if locale and isinstance(locale, i18n.Locale): locale = i18n.get_identifier_from_locale_class(locale) + # remove __ckan_no_root and add after to not pollute url no_root = kw.pop('__ckan_no_root', False) - # routes will get the wrong url for APIs if the ver is not provided - if kw.get('controller') == 'api': + + # All API URLs generated should provide the version number + if kw.get('controller') == 'api' or args and args[0].startswith('api.'): ver = kw.get('ver') if not ver: - raise Exception('api calls must specify the version! e.g. ver=3') - # fix ver to include the slash - kw['ver'] = '/%s' % ver - if kw.get('qualified', False): - kw['protocol'], kw['host'] = get_site_protocol_and_host() - my_url = _routes_default_url_for(*args, **kw) + raise Exception('API URLs must specify the version (eg ver=3)') + + try: + # First try to build the URL with the Flask router, making a copy of + # the params in case they are modified + flask_args = tuple(args) + flask_kw = kw.copy() + + my_url = _url_for_flask(*flask_args, **flask_kw) + + except FlaskRouteBuildError: + # If it doesn't succeed, fallback to the Pylons router, using the + # original parameters + my_url = _url_for_pylons(*args, **kw) + + # Add back internal params kw['__ckan_no_root'] = no_root + + # Rewrite the URL to take the locale and root_path into account return _local_url(my_url, locale=locale, **kw) +def _url_for_flask(*args, **kw): + '''Build a URL using the Flask router + + This function should not be called directly, use ``url_for`` instead + + This function tries to support the Pylons syntax for ``url_for`` and adapt + it to the Flask one, eg:: + + # Pylons + url_for(controller='api', action='action', ver=3, qualified=True) + + # Flask + url_for('api.action', ver=3, _external=True) + + + Raises :py:exception:`werkzeug.routing.BuildError` if it couldn't + generate a URL. + ''' + if (len(args) and '_' in args[0] + and '.' not in args[0] + and not args[0].startswith('/')): + # Try to translate Python named routes to Flask endpoints + # eg `dataset_new` -> `dataset.new` + args = (args[0].replace('_', '.', 1), ) + elif kw.get('controller') and kw.get('action'): + # If `controller` and `action` are passed, build a Flask endpoint + # from them + # eg controller='user', action='login' -> 'user.login' + args = ('{0}.{1}'.format(kw.pop('controller'), kw.pop('action')),) + + # Support Pylons' way of asking for full URLs + + external = kw.pop('_external', False) or kw.pop('qualified', False) + + # The API routes used to require a slash on the version number, make sure + # we remove it + if (args and args[0].startswith('api.') and + isinstance(kw.get('ver'), basestring) and + kw['ver'].startswith('/')): + kw['ver'] = kw['ver'].replace('/', '') + + # Try to build the URL with flask.url_for + my_url = _flask_default_url_for(*args, **kw) + + if external: + # Don't rely on the host generated by Flask, as SERVER_NAME might not + # be set or might be not be up to date (as in tests changing + # `ckan.site_url`). Contrary to the Routes mapper, there is no way in + # Flask to pass the host explicitly, so we rebuild the URL manually + # based on `ckan.site_url`, which is essentially what we did on Pylons + protocol, host = get_site_protocol_and_host() + parts = urlparse.urlparse(my_url) + my_url = urlparse.urlunparse((protocol, host, parts.path, parts.params, + parts.query, parts.fragment)) + + return my_url + + +def _url_for_pylons(*args, **kw): + '''Build a URL using the Pylons (Routes) router + + This function should not be called directly, use ``url_for`` instead + ''' + + # We need to provide protocol and host to get full URLs, get them from + # ckan.site_url + if kw.get('qualified', False) or kw.get('_external', False): + kw['protocol'], kw['host'] = get_site_protocol_and_host() + + # The Pylons API routes require a slask on the version number for some + # reason + if kw.get('controller') == 'api' and kw.get('ver'): + if (isinstance(kw['ver'], int) or + not kw['ver'].startswith('/')): + kw['ver'] = '/%s' % kw['ver'] + + # Try to build the URL with routes.url_for + return _routes_default_url_for(*args, **kw) + + @core_helper def url_for_static(*args, **kw): '''Returns the URL for static content that doesn't get translated (eg CSS) diff --git a/ckan/tests/config/test_middleware.py b/ckan/tests/config/test_middleware.py index b0c20b46984..d5faf4a3590 100644 --- a/ckan/tests/config/test_middleware.py +++ b/ckan/tests/config/test_middleware.py @@ -9,6 +9,7 @@ import ckan.model as model import ckan.plugins as p +import ckan.lib.helpers as h import ckan.tests.helpers as helpers import ckan.tests.factories as factories from ckan.common import config @@ -547,12 +548,15 @@ def test_user_objects_in_c_sysadmin(self): p.unload('test_routing_plugin') +_test_controller = 'ckan.tests.config.test_middleware:MockPylonsController' + + class MockRoutingPlugin(p.SingletonPlugin): p.implements(p.IRoutes) p.implements(p.IBlueprint) - controller = 'ckan.tests.config.test_middleware:MockPylonsController' + controller = _test_controller def before_map(self, _map): @@ -570,6 +574,9 @@ def before_map(self, _map): _map.connect('/hello', controller=self.controller, action='view') + _map.connect('/pylons_route_flask_url_for', + controller=self.controller, action='test_flask_url_for') + return _map def after_map(self, _map): @@ -589,6 +596,10 @@ def get_blueprint(self): blueprint.add_url_rule('/simple_flask', 'flask_plugin_view', flask_plugin_view) + blueprint.add_url_rule('/flask_route_pylons_url_for', + 'flask_route_pylons_url_for', + flask_plugin_view_url_for) + return blueprint @@ -596,11 +607,20 @@ def flask_plugin_view(): return 'Hello World, this is served from a Flask extension' +def flask_plugin_view_url_for(): + url = h.url_for(controller=_test_controller, action='view') + return 'This URL was generated by Pylons: {0}'.format(url) + + class MockPylonsController(p.toolkit.BaseController): def view(self): return 'Hello World, this is served from a Pylons extension' + def test_flask_url_for(self): + url = h.url_for('api.get_api', ver=3) + return 'This URL was generated by Flask: {0}'.format(url) + class TestSecretKey(object): diff --git a/ckan/tests/lib/test_helpers.py b/ckan/tests/lib/test_helpers.py index 010f817f096..0b67f25c353 100644 --- a/ckan/tests/lib/test_helpers.py +++ b/ckan/tests/lib/test_helpers.py @@ -5,6 +5,7 @@ import tzlocal from babel import Locale +from ckan.common import config import ckan.lib.helpers as h import ckan.plugins as p import ckan.exceptions @@ -17,7 +18,33 @@ CkanUrlException = ckan.exceptions.CkanUrlException -class TestHelpersUrlForStatic(object): +class BaseUrlFor(object): + + @classmethod + def setup_class(cls): + + # Make a copy of the Pylons config, so we can restore it in teardown. + cls._original_config = dict(config) + config['ckan.site_url'] = 'http://example.com' + cls.app = helpers._get_test_app() + + def setup(self): + + self.request_context = self.app.flask_app.test_request_context() + self.request_context.push() + + def teardown(self): + + self.request_context.pop() + + @classmethod + def teardown_class(cls): + # Restore the config to its original values + config.clear() + config.update(cls._original_config) + + +class TestHelpersUrlForStatic(BaseUrlFor): def test_url_for_static(self): url = '/assets/ckan.jpg' @@ -51,7 +78,8 @@ def test_url_for_static_with_root_path(self): @helpers.change_config('ckan.root_path', '/my/custom/path/{{LANG}}/foo') def test_url_for_static_qualified_with_root_path(self): url = 'http://example.com/my/custom/path/foo/my-asset/file.txt' - generated_url = h.url_for_static('/my-asset/file.txt', qualified=True) + generated_url = h.url_for_static('/my-asset/file.txt', + qualified=True) eq_(generated_url, url) @helpers.set_extra_environ('SCRIPT_NAME', '/my/custom/path') @@ -59,11 +87,12 @@ def test_url_for_static_qualified_with_root_path(self): @helpers.change_config('ckan.root_path', '/my/custom/path/{{LANG}}/foo') def test_url_for_static_with_root_path_and_script_name_env(self): url = 'http://example.com/my/custom/path/foo/my-asset/file.txt' - generated_url = h.url_for_static('/my-asset/file.txt', qualified=True) + generated_url = h.url_for_static('/my-asset/file.txt', + qualified=True) eq_(generated_url, url) -class TestHelpersUrlForStaticOrExternal(object): +class TestHelpersUrlForStaticOrExternal(BaseUrlFor): def test_url_for_static_or_external(self): url = '/assets/ckan.jpg' @@ -87,12 +116,13 @@ def test_url_for_static_or_external_works_with_protocol_relative_url(self): eq_(h.url_for_static_or_external(url), url) -class TestHelpersUrlFor(object): +class TestHelpersUrlFor(BaseUrlFor): @helpers.change_config('ckan.site_url', 'http://example.com') def test_url_for_default(self): url = '/dataset/my_dataset' - generated_url = h.url_for(controller='package', action='read', id='my_dataset') + generated_url = h.url_for(controller='package', action='read', + id='my_dataset') eq_(generated_url, url) @helpers.change_config('ckan.site_url', 'http://example.com') @@ -174,6 +204,91 @@ def test_url_for_qualified_with_root_path_locale_and_script_name_env(self): eq_(generated_url, url) + +class TestHelpersUrlForFlaskandPylons2(BaseUrlFor): + + def test_url_for_flask_route_new_syntax(self): + url = '/api/3' + generated_url = h.url_for('api.get_api', ver=3) + eq_(generated_url, url) + + +class TestHelpersUrlForFlaskandPylons(BaseUrlFor): + + def test_url_for_flask_route_new_syntax(self): + url = '/api/3' + generated_url = h.url_for('api.get_api', ver=3) + eq_(generated_url, url) + + def test_url_for_flask_route_old_syntax(self): + url = '/api/3' + generated_url = h.url_for(controller='api', action='get_api', ver=3) + eq_(generated_url, url) + + @helpers.change_config('ckan.site_url', 'http://example.com') + def test_url_for_flask_route_new_syntax_external(self): + url = 'http://example.com/api/3' + generated_url = h.url_for('api.get_api', ver=3, _external=True) + eq_(generated_url, url) + + @helpers.change_config('ckan.site_url', 'http://example.com') + def test_url_for_flask_route_old_syntax_external(self): + url = 'http://example.com/api/3' + generated_url = h.url_for(controller='api', action='get_api', ver=3, _external=True) + eq_(generated_url, url) + + @helpers.change_config('ckan.site_url', 'http://example.com') + def test_url_for_flask_route_old_syntax_qualified(self): + url = 'http://example.com/api/3' + generated_url = h.url_for(controller='api', action='get_api', ver=3, qualified=True) + eq_(generated_url, url) + + @helpers.change_config('ckan.site_url', 'http://example.com') + def test_url_for_flask_route_new_syntax_site_url(self): + url = '/api/3' + generated_url = h.url_for('api.get_api', ver=3) + eq_(generated_url, url) + + @helpers.change_config('ckan.site_url', 'http://example.com') + def test_url_for_flask_route_old_syntax_site_url(self): + url = '/api/3' + generated_url = h.url_for(controller='api', action='get_api', ver=3) + eq_(generated_url, url) + + def test_url_for_flask_route_new_syntax_request_context(self): + with self.app.flask_app.test_request_context(): + url = '/api/3' + generated_url = h.url_for('api.get_api', ver=3) + eq_(generated_url, url) + + def test_url_for_flask_request_using_pylons_url_for(self): + + if not p.plugin_loaded('test_routing_plugin'): + p.load('test_routing_plugin') + plugin = p.get_plugin('test_routing_plugin') + self.app.flask_app.register_extension_blueprint( + plugin.get_blueprint()) + + res = self.app.get('/flask_route_pylons_url_for') + + assert u'This URL was generated by Pylons' in res.ubody + assert u'/from_pylons_extension_before_map' in res.ubody + + p.unload('test_routing_plugin') + + def test_url_for_pylons_request_using_flask_url_for(self): + + if not p.plugin_loaded('test_routing_plugin'): + p.load('test_routing_plugin') + + res = self.app.get('/pylons_route_flask_url_for') + + assert u'This URL was generated by Flask' in res.ubody + assert u'/api/3' in res.ubody + + p.unload('test_routing_plugin') + + class TestHelpersRenderMarkdown(object): def test_render_markdown_allow_html(self): From 9b9313fb5176fb0fec81f9db1973a389b4c28025 Mon Sep 17 00:00:00 2001 From: amercader Date: Wed, 31 Aug 2016 10:35:51 +0100 Subject: [PATCH 03/71] [#3196] Fix redirect import --- ckan/tests/config/test_sessions.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ckan/tests/config/test_sessions.py b/ckan/tests/config/test_sessions.py index 4c61716eca1..bb0d2a847bf 100644 --- a/ckan/tests/config/test_sessions.py +++ b/ckan/tests/config/test_sessions.py @@ -6,7 +6,6 @@ from flask import render_template from flask import redirect as flask_redirect from flask import url_for -from ckan.lib.base import redirect as pylons_redirect from ckan.lib.base import render as pylons_render import ckan.plugins as p @@ -126,4 +125,4 @@ def flash_message_action(self): def add_flash_message_redirect(self): # Adds a flash message and redirects to flask view h.flash_success(u'This is a success message populated by Pylons') - return pylons_redirect(u'/flask_view_flash_message') + return h.redirect_to(u'/flask_view_flash_message') From 43767c78390f389b62767f7e38cfdba7d68a958b Mon Sep 17 00:00:00 2001 From: amercader Date: Thu, 1 Sep 2016 11:49:18 +0100 Subject: [PATCH 04/71] [#3196] Fix ckan/ tests (no legacy) depending on url_for The Flask url_for function requires an application context to be present when generating a url_for. This is obviously not the case when calling it from a test, so we need to wrap the function on a test_request_context (which will create an app context): with app.flask_app.test_request_context(): url_for(...) For tests that don't require an app like helpers or mailer this is done automatically in the tests setup. Note that all URLs generated now take ckan.site_url into account, so tests checking for `http://localhost/some-url` will fail as the correct url is `http://test.ckan.net/some-url`, as this is the site_url used on test-core.ini. --- ckan/lib/alphabet_paginate.py | 2 +- ckan/tests/config/test_middleware.py | 5 +- ckan/tests/config/test_sessions.py | 4 +- ckan/tests/controllers/test_admin.py | 36 +- ckan/tests/controllers/test_api.py | 101 ++-- ckan/tests/controllers/test_feed.py | 42 +- ckan/tests/controllers/test_group.py | 249 +++++--- ckan/tests/controllers/test_home.py | 49 +- ckan/tests/controllers/test_organization.py | 247 +++++--- ckan/tests/controllers/test_package.py | 638 +++++++++++++------- ckan/tests/controllers/test_tags.py | 20 +- ckan/tests/controllers/test_user.py | 173 ++++-- ckan/tests/controllers/test_util.py | 28 +- ckan/tests/lib/test_helpers.py | 1 - ckan/tests/lib/test_mailer.py | 39 +- ckan/tests/logic/action/test_create.py | 6 +- 16 files changed, 1091 insertions(+), 549 deletions(-) diff --git a/ckan/lib/alphabet_paginate.py b/ckan/lib/alphabet_paginate.py index 0fdf8d60cf8..99e570af055 100644 --- a/ckan/lib/alphabet_paginate.py +++ b/ckan/lib/alphabet_paginate.py @@ -21,7 +21,7 @@ from sqlalchemy import __version__ as sqav from sqlalchemy.orm.query import Query from webhelpers.html.builder import HTML -from routes import url_for +from ckan.lib.helpers import url_for class AlphaPage(object): diff --git a/ckan/tests/config/test_middleware.py b/ckan/tests/config/test_middleware.py index d5faf4a3590..e1f9538d44f 100644 --- a/ckan/tests/config/test_middleware.py +++ b/ckan/tests/config/test_middleware.py @@ -3,7 +3,6 @@ import mock import wsgiref from nose.tools import assert_equals, assert_not_equals, eq_, assert_raises -from routes import url_for from flask import Blueprint import flask @@ -30,7 +29,9 @@ def test_homepage_with_middleware_activated(self): We are just testing the home page renders without any troubles and that the middleware has not done anything strange to the response string''' app = self._get_test_app() - response = app.get(url=url_for(controller='home', action='index')) + with app.flask_app.test_request_context(): + response = app.get( + url=h.url_for(controller='home', action='index')) assert_equals(200, response.status_int) # make sure we haven't overwritten the response too early. diff --git a/ckan/tests/config/test_sessions.py b/ckan/tests/config/test_sessions.py index bb0d2a847bf..6a861e70b99 100644 --- a/ckan/tests/config/test_sessions.py +++ b/ckan/tests/config/test_sessions.py @@ -5,7 +5,6 @@ from flask import Blueprint from flask import render_template from flask import redirect as flask_redirect -from flask import url_for from ckan.lib.base import render as pylons_render import ckan.plugins as p @@ -73,7 +72,8 @@ def flash_message_view(self): def add_flash_message_view_redirect_to_flask(self): u'''Add flash message, then redirect to Flask view to render it.''' h.flash_success(u'This is a success message populated by Flask') - return flask_redirect(url_for(u'test_flash_plugin.flash_message_view')) + return flask_redirect( + h.url_for(u'test_flash_plugin.flash_message_view')) def add_flash_message_view_redirect_to_pylons(self): u'''Add flash message, then redirect to view that renders it''' diff --git a/ckan/tests/controllers/test_admin.py b/ckan/tests/controllers/test_admin.py index 8915c489d92..7b1c6067839 100644 --- a/ckan/tests/controllers/test_admin.py +++ b/ckan/tests/controllers/test_admin.py @@ -3,7 +3,7 @@ from nose.tools import assert_true, assert_equal from bs4 import BeautifulSoup -from routes import url_for +from ckan.lib.helpers import url_for from ckan.common import config import ckan.model as model @@ -19,8 +19,10 @@ def _get_admin_config_page(app): user = factories.Sysadmin() env = {'REMOTE_USER': user['name'].encode('ascii')} + with app.flask_app.test_request_context(): + url = url_for(controller='admin', action='config') response = app.get( - url=url_for(controller='admin', action='config'), + url=url, extra_environ=env, ) return env, response @@ -30,8 +32,10 @@ def _reset_config(app): '''Reset config via action''' user = factories.Sysadmin() env = {'REMOTE_USER': user['name'].encode('ascii')} + with app.flask_app.test_request_context(): + url = url_for(controller='admin', action='reset_config') app.post( - url=url_for(controller='admin', action='reset_config'), + url=url, extra_environ=env, ) @@ -262,9 +266,9 @@ class TestTrashView(helpers.FunctionalTestBase): def test_trash_view_anon_user(self): '''An anon user shouldn't be able to access trash view.''' app = self._get_test_app() - - trash_url = url_for(controller='admin', action='trash') - trash_response = app.get(trash_url, status=403) + with app.flask_app.test_request_context(): + trash_url = url_for(controller='admin', action='trash') + app.get(trash_url, status=403) def test_trash_view_normal_user(self): '''A normal logged in user shouldn't be able to access trash view.''' @@ -272,7 +276,9 @@ def test_trash_view_normal_user(self): app = self._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} - trash_url = url_for(controller='admin', action='trash') + + with app.flask_app.test_request_context(): + trash_url = url_for(controller='admin', action='trash') trash_response = app.get(trash_url, extra_environ=env, status=403) assert_true('Need to be system administrator to administer' in trash_response) @@ -283,7 +289,9 @@ def test_trash_view_sysadmin(self): app = self._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} - trash_url = url_for(controller='admin', action='trash') + + with app.flask_app.test_request_context(): + trash_url = url_for(controller='admin', action='trash') trash_response = app.get(trash_url, extra_environ=env, status=200) # On the purge page assert_true('form-purge-packages' in trash_response) @@ -296,7 +304,8 @@ def test_trash_no_datasets(self): app = self._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} - trash_url = url_for(controller='admin', action='trash') + with app.flask_app.test_request_context(): + trash_url = url_for(controller='admin', action='trash') trash_response = app.get(trash_url, extra_environ=env, status=200) trash_response_html = BeautifulSoup(trash_response.body) @@ -315,7 +324,8 @@ def test_trash_with_deleted_datasets(self): app = self._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} - trash_url = url_for(controller='admin', action='trash') + with app.flask_app.test_request_context(): + trash_url = url_for(controller='admin', action='trash') trash_response = app.get(trash_url, extra_environ=env, status=200) trash_response_html = BeautifulSoup(trash_response.body) @@ -338,7 +348,8 @@ def test_trash_purge_deleted_datasets(self): assert_equal(pkgs_before_purge, 3) env = {'REMOTE_USER': user['name'].encode('ascii')} - trash_url = url_for(controller='admin', action='trash') + with app.flask_app.test_request_context(): + trash_url = url_for(controller='admin', action='trash') trash_response = app.get(trash_url, extra_environ=env, status=200) # submit the purge form @@ -364,7 +375,8 @@ def _update_config_option(self): sysadmin = factories.Sysadmin() env = {'REMOTE_USER': sysadmin['name'].encode('ascii')} app = self._get_test_app() - url = url_for(controller='admin', action='config') + with app.flask_app.test_request_context(): + url = url_for(controller='admin', action='config') response = app.get(url=url, extra_environ=env) form = response.forms[1] diff --git a/ckan/tests/controllers/test_api.py b/ckan/tests/controllers/test_api.py index d674bb02f66..def1a1aaea0 100644 --- a/ckan/tests/controllers/test_api.py +++ b/ckan/tests/controllers/test_api.py @@ -7,7 +7,7 @@ import json import re -from routes import url_for +from ckan.lib.helpers import url_for from nose.tools import assert_equal, assert_in, eq_ import ckan.tests.helpers as helpers @@ -30,9 +30,12 @@ def test_unicode_in_error_message_works_ok(self): def test_dataset_autocomplete_name(self): dataset = factories.Dataset(name='rivers') - url = url_for(controller='api', action='dataset_autocomplete', ver='/2') - assert_equal(url, '/api/2/util/dataset/autocomplete') + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='api', action='dataset_autocomplete', + ver='/2') + assert_equal(url, '/api/2/util/dataset/autocomplete') response = app.get( url=url, @@ -54,7 +57,11 @@ def test_dataset_autocomplete_name(self): def test_dataset_autocomplete_title(self): dataset = factories.Dataset(name='test_ri', title='Rivers') - url = url_for(controller='api', action='dataset_autocomplete', ver='/2') + + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='api', action='dataset_autocomplete', + ver='/2') assert_equal(url, '/api/2/util/dataset/autocomplete') app = self._get_test_app() @@ -78,9 +85,12 @@ def test_dataset_autocomplete_title(self): def test_tag_autocomplete(self): factories.Dataset(tags=[{'name': 'rivers'}]) - url = url_for(controller='api', action='tag_autocomplete', ver='/2') - assert_equal(url, '/api/2/util/tag/autocomplete') + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='api', action='tag_autocomplete', + ver='/2') + assert_equal(url, '/api/2/util/tag/autocomplete') response = app.get( url=url, @@ -96,10 +106,12 @@ def test_tag_autocomplete(self): 'application/json;charset=utf-8') def test_group_autocomplete_by_name(self): - org = factories.Group(name='rivers', title='Bridges') - url = url_for(controller='api', action='group_autocomplete', ver='/2') - assert_equal(url, '/api/2/util/group/autocomplete') + factories.Group(name='rivers', title='Bridges') app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='api', action='group_autocomplete', + ver='/2') + assert_equal(url, '/api/2/util/group/autocomplete') response = app.get( url=url, @@ -117,9 +129,11 @@ def test_group_autocomplete_by_name(self): 'application/json;charset=utf-8') def test_group_autocomplete_by_title(self): - org = factories.Group(name='frogs', title='Bugs') - url = url_for(controller='api', action='group_autocomplete', ver='/2') + factories.Group(name='frogs', title='Bugs') app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='api', action='group_autocomplete', + ver='/2') response = app.get( url=url, @@ -135,9 +149,12 @@ def test_group_autocomplete_by_title(self): def test_organization_autocomplete_by_name(self): org = factories.Organization(name='simple-dummy-org') - url = url_for(controller='api', action='organization_autocomplete', ver='/2') - assert_equal(url, '/api/2/util/organization/autocomplete') + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='api', action='organization_autocomplete', + ver='/2') + assert_equal(url, '/api/2/util/organization/autocomplete') response = app.get( url=url, @@ -155,9 +172,12 @@ def test_organization_autocomplete_by_name(self): 'application/json;charset=utf-8') def test_organization_autocomplete_by_title(self): - org = factories.Organization(title='Simple dummy org') - url = url_for(controller='api', action='organization_autocomplete', ver='/2') + factories.Organization(title='Simple dummy org') + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='api', action='organization_autocomplete', + ver='/2') response = app.get( url=url, @@ -173,12 +193,14 @@ def test_organization_autocomplete_by_title(self): def test_config_option_list_access_sysadmin(self): user = factories.Sysadmin() - url = url_for( - controller='api', - action='action', - logic_function='config_option_list', - ver='/3') + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for( + controller='api', + action='action', + logic_function='config_option_list', + ver='/3') app.get( url=url, @@ -189,12 +211,14 @@ def test_config_option_list_access_sysadmin(self): def test_config_option_list_access_sysadmin_jsonp(self): user = factories.Sysadmin() - url = url_for( - controller='api', - action='action', - logic_function='config_option_list', - ver='/3') + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for( + controller='api', + action='action', + logic_function='config_option_list', + ver='/3') app.get( url=url, @@ -208,12 +232,13 @@ def test_jsonp_works_on_get_requests(self): dataset1 = factories.Dataset() dataset2 = factories.Dataset() - url = url_for( - controller='api', - action='action', - logic_function='package_list', - ver='/3') app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for( + controller='api', + action='action', + logic_function='package_list', + ver='/3') res = app.get( url=url, params={'callback': 'my_callback'}, @@ -230,15 +255,15 @@ def test_jsonp_does_not_work_on_post_requests(self): dataset1 = factories.Dataset() dataset2 = factories.Dataset() - - url = url_for( - controller='api', - action='action', - logic_function='package_list', - ver='/3', - callback='my_callback', - ) app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for( + controller='api', + action='action', + logic_function='package_list', + ver='/3', + callback='my_callback', + ) res = app.post( url=url, ) diff --git a/ckan/tests/controllers/test_feed.py b/ckan/tests/controllers/test_feed.py index 1e4c516e029..6643d06ad7c 100644 --- a/ckan/tests/controllers/test_feed.py +++ b/ckan/tests/controllers/test_feed.py @@ -1,6 +1,6 @@ # encoding: utf-8 -from routes import url_for +from ckan.lib.helpers import url_for import ckan.tests.helpers as helpers import ckan.tests.factories as factories @@ -14,32 +14,40 @@ def teardown_class(cls): def test_atom_feed_page_zero_gives_error(self): group = factories.Group() - offset = url_for(controller='feed', action='group', - id=group['name']) + '?page=0' + app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='feed', action='group', + id=group['name']) + '?page=0' res = app.get(offset, status=400) assert '"page" parameter must be a positive integer' in res, res def test_atom_feed_page_negative_gives_error(self): group = factories.Group() - offset = url_for(controller='feed', action='group', - id=group['name']) + '?page=-2' + app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='feed', action='group', + id=group['name']) + '?page=-2' res = app.get(offset, status=400) assert '"page" parameter must be a positive integer' in res, res def test_atom_feed_page_not_int_gives_error(self): group = factories.Group() - offset = url_for(controller='feed', action='group', - id=group['name']) + '?page=abc' + app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='feed', action='group', + id=group['name']) + '?page=abc' res = app.get(offset, status=400) assert '"page" parameter must be a positive integer' in res, res def test_general_atom_feed_works(self): dataset = factories.Dataset() - offset = url_for(controller='feed', action='general') + app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='feed', action='general') res = app.get(offset) assert '{0}'.format(dataset['title']) in res.body @@ -47,9 +55,11 @@ def test_general_atom_feed_works(self): def test_group_atom_feed_works(self): group = factories.Group() dataset = factories.Dataset(groups=[{'id': group['id']}]) - offset = url_for(controller='feed', action='group', - id=group['name']) + app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='feed', action='group', + id=group['name']) res = app.get(offset) assert '{0}'.format(dataset['title']) in res.body @@ -57,9 +67,11 @@ def test_group_atom_feed_works(self): def test_organization_atom_feed_works(self): group = factories.Organization() dataset = factories.Dataset(owner_org=group['id']) - offset = url_for(controller='feed', action='organization', - id=group['name']) + app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='feed', action='organization', + id=group['name']) res = app.get(offset) assert '{0}'.format(dataset['title']) in res.body @@ -71,11 +83,13 @@ def test_custom_atom_feed_works(self): dataset2 = factories.Dataset( title='Test daily', extras=[{'key': 'frequency', 'value': 'daily'}]) - offset = url_for(controller='feed', action='custom') + + app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='feed', action='custom') params = { 'q': 'frequency:weekly' } - app = self._get_test_app() res = app.get(offset, params=params) assert '{0}'.format(dataset1['title']) in res.body diff --git a/ckan/tests/controllers/test_group.py b/ckan/tests/controllers/test_group.py index 67e06c92ce9..4fc9d9b8bc4 100644 --- a/ckan/tests/controllers/test_group.py +++ b/ckan/tests/controllers/test_group.py @@ -3,7 +3,7 @@ from bs4 import BeautifulSoup from nose.tools import assert_equal, assert_true, assert_in -from routes import url_for +from ckan.lib.helpers import url_for import ckan.tests.helpers as helpers import ckan.model as model @@ -19,17 +19,22 @@ def setup(self): model.repo.rebuild_db() def test_bulk_process_throws_404_for_nonexistent_org(self): + app = self._get_test_app() - bulk_process_url = url_for(controller='organization', - action='bulk_process', id='does-not-exist') + with app.flask_app.test_request_context(): + bulk_process_url = url_for( + controller='organization', action='bulk_process', + id='does-not-exist') app.get(url=bulk_process_url, status=404) def test_page_thru_list_of_orgs_preserves_sort_order(self): orgs = [factories.Organization() for _ in range(35)] app = self._get_test_app() - org_url = url_for(controller='organization', - action='index', - sort='name desc') + + with app.flask_app.test_request_context(): + org_url = url_for(controller='organization', + action='index', + sort='name desc') response = app.get(url=org_url) assert orgs[-1]['name'] in response assert orgs[0]['name'] not in response @@ -41,9 +46,11 @@ def test_page_thru_list_of_orgs_preserves_sort_order(self): def test_page_thru_list_of_groups_preserves_sort_order(self): groups = [factories.Group() for _ in range(35)] app = self._get_test_app() - group_url = url_for(controller='group', - action='index', - sort='title desc') + + with app.flask_app.test_request_context(): + group_url = url_for(controller='group', + action='index', + sort='title desc') response = app.get(url=group_url) assert groups[-1]['title'] in response @@ -57,8 +64,11 @@ def test_page_thru_list_of_groups_preserves_sort_order(self): def _get_group_new_page(app): user = factories.User() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='group', action='new') response = app.get( - url=url_for(controller='group', action='new'), + url=url, extra_environ=env, ) return env, response @@ -67,7 +77,9 @@ def _get_group_new_page(app): class TestGroupControllerNew(helpers.FunctionalTestBase): def test_not_logged_in(self): app = self._get_test_app() - app.get(url=url_for(controller='group', action='new'), + with app.flask_app.test_request_context(): + url = url_for(controller='group', action='new') + app.get(url=url, status=403) def test_form_renders(self): @@ -117,9 +129,11 @@ def _get_group_edit_page(app, group_name=None): group = factories.Group(user=user) group_name = group['name'] env = {'REMOTE_USER': user['name'].encode('ascii')} - url = url_for(controller='group', - action='edit', - id=group_name) + + with app.flask_app.test_request_context(): + url = url_for(controller='group', + action='edit', + id=group_name) response = app.get(url=url, extra_environ=env) return env, response, group_name @@ -127,16 +141,21 @@ def _get_group_edit_page(app, group_name=None): class TestGroupControllerEdit(helpers.FunctionalTestBase): def test_not_logged_in(self): app = self._get_test_app() - app.get(url=url_for(controller='group', action='new'), + + with app.flask_app.test_request_context(): + url = url_for(controller='group', action='new') + app.get(url=url, status=403) def test_group_doesnt_exist(self): app = self._get_test_app() user = factories.User() env = {'REMOTE_USER': user['name'].encode('ascii')} - url = url_for(controller='group', - action='edit', - id='doesnt_exist') + + with app.flask_app.test_request_context(): + url = url_for(controller='group', + action='edit', + id='doesnt_exist') app.get(url=url, extra_environ=env, status=404) @@ -173,17 +192,19 @@ def test_all_fields_saved(self): class TestGroupRead(helpers.FunctionalTestBase): def setup(self): super(TestGroupRead, self).setup() - self.app = helpers._get_test_app() self.user = factories.User() self.user_env = {'REMOTE_USER': self.user['name'].encode('ascii')} self.group = factories.Group(user=self.user) def test_group_read(self): - response = self.app.get(url=url_for(controller='group', - action='read', - id=self.group['id']), - status=200, - extra_environ=self.user_env) + + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='group', action='read', + id=self.group['id']) + response = app.get(url=url, + status=200, + extra_environ=self.user_env) assert_in(self.group['title'], response) assert_in(self.group['description'], response) @@ -197,53 +218,69 @@ def setup(self): self.group = factories.Group(user=self.user) def test_owner_delete(self): - response = self.app.get(url=url_for(controller='group', - action='delete', - id=self.group['id']), - status=200, - extra_environ=self.user_env) + + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='group', action='delete', + id=self.group['id']) + + response = app.get(url=url, + status=200, + extra_environ=self.user_env) form = response.forms['group-confirm-delete-form'] - response = submit_and_follow(self.app, form, name='delete', + response = submit_and_follow(app, form, name='delete', extra_environ=self.user_env) group = helpers.call_action('group_show', id=self.group['id']) assert_equal(group['state'], 'deleted') def test_sysadmin_delete(self): + + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='group', action='delete', + id=self.group['id']) + sysadmin = factories.Sysadmin() extra_environ = {'REMOTE_USER': sysadmin['name'].encode('ascii')} - response = self.app.get(url=url_for(controller='group', - action='delete', - id=self.group['id']), - status=200, - extra_environ=extra_environ) + response = app.get(url=url, + status=200, + extra_environ=extra_environ) form = response.forms['group-confirm-delete-form'] - response = submit_and_follow(self.app, form, name='delete', + response = submit_and_follow(app, form, name='delete', extra_environ=self.user_env) group = helpers.call_action('group_show', id=self.group['id']) assert_equal(group['state'], 'deleted') def test_non_authorized_user_trying_to_delete_fails(self): + + app = self._get_test_app() user = factories.User() extra_environ = {'REMOTE_USER': user['name'].encode('ascii')} - self.app.get(url=url_for(controller='group', - action='delete', - id=self.group['id']), - status=403, - extra_environ=extra_environ) + with app.flask_app.test_request_context(): + url = url_for(controller='group', action='delete', + id=self.group['id']) + + app.get(url=url, + status=403, + extra_environ=extra_environ) group = helpers.call_action('group_show', id=self.group['id']) assert_equal(group['state'], 'active') def test_anon_user_trying_to_delete_fails(self): - self.app.get(url=url_for(controller='group', - action='delete', - id=self.group['id']), - status=403) + + app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='group', action='delete', + id=self.group['id']) + + app.get(url=url, + status=403) group = helpers.call_action('group_show', id=self.group['id']) @@ -264,9 +301,11 @@ def _create_group(self, owner_username, users=None): def _get_group_add_member_page(self, app, user, group_name): env = {'REMOTE_USER': user['name'].encode('ascii')} - url = url_for(controller='group', - action='member_new', - id=group_name) + + with app.flask_app.test_request_context(): + url = url_for(controller='group', + action='member_new', + id=group_name) response = app.get(url=url, extra_environ=env) return env, response @@ -282,8 +321,9 @@ def test_membership_list(self): group = self._create_group(user_one['name'], other_users) - member_list_url = url_for(controller='group', action='members', - id=group['id']) + with app.flask_app.test_request_context(): + member_list_url = url_for(controller='group', action='members', + id=group['id']) member_list_response = app.get(member_list_url) assert_true('2 members' in member_list_response) @@ -369,8 +409,9 @@ def test_remove_member(self): group = self._create_group(user_one['name'], other_users) - remove_url = url_for(controller='group', action='member_delete', - user=user_two['id'], id=group['id']) + with app.flask_app.test_request_context(): + remove_url = url_for(controller='group', action='member_delete', + user=user_two['id'], id=group['id']) env = {'REMOTE_USER': user_one['name'].encode('ascii')} remove_response = app.post(remove_url, extra_environ=env, status=302) @@ -402,9 +443,11 @@ def test_group_follow(self): group = factories.Group() env = {'REMOTE_USER': user['name'].encode('ascii')} - follow_url = url_for(controller='group', - action='follow', - id=group['id']) + + with app.flask_app.test_request_context(): + follow_url = url_for(controller='group', + action='follow', + id=group['id']) response = app.post(follow_url, extra_environ=env, status=302) response = response.follow() assert_true('You are now following {0}' @@ -418,9 +461,11 @@ def test_group_follow_not_exist(self): user_one = factories.User() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - follow_url = url_for(controller='group', - action='follow', - id='not-here') + + with app.flask_app.test_request_context(): + follow_url = url_for(controller='group', + action='follow', + id='not-here') response = app.post(follow_url, extra_environ=env, status=404) assert_true('Group not found' in response) @@ -431,13 +476,16 @@ def test_group_unfollow(self): group = factories.Group() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - follow_url = url_for(controller='group', - action='follow', - id=group['id']) + + with app.flask_app.test_request_context(): + follow_url = url_for(controller='group', + action='follow', + id=group['id']) + unfollow_url = url_for(controller='group', action='unfollow', + id=group['id']) + app.post(follow_url, extra_environ=env, status=302) - unfollow_url = url_for(controller='group', action='unfollow', - id=group['id']) unfollow_response = app.post(unfollow_url, extra_environ=env, status=302) unfollow_response = unfollow_response.follow() @@ -454,8 +502,10 @@ def test_group_unfollow_not_following(self): group = factories.Group() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - unfollow_url = url_for(controller='group', action='unfollow', - id=group['id']) + + with app.flask_app.test_request_context(): + unfollow_url = url_for(controller='group', action='unfollow', + id=group['id']) unfollow_response = app.post(unfollow_url, extra_environ=env, status=302) unfollow_response = unfollow_response.follow() @@ -470,8 +520,10 @@ def test_group_unfollow_not_exist(self): user_one = factories.User() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - unfollow_url = url_for(controller='group', action='unfollow', - id='not-here') + + with app.flask_app.test_request_context(): + unfollow_url = url_for(controller='group', action='unfollow', + id='not-here') unfollow_response = app.post(unfollow_url, extra_environ=env, status=404) assert_true('Group not found' in unfollow_response) @@ -484,13 +536,15 @@ def test_group_follower_list(self): group = factories.Group() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - follow_url = url_for(controller='group', - action='follow', - id=group['id']) - app.post(follow_url, extra_environ=env, status=302) - followers_url = url_for(controller='group', action='followers', - id=group['id']) + with app.flask_app.test_request_context(): + follow_url = url_for(controller='group', + action='follow', + id=group['id']) + followers_url = url_for(controller='group', action='followers', + id=group['id']) + + app.post(follow_url, extra_environ=env, status=302) # Only sysadmins can view the followers list pages followers_response = app.get(followers_url, extra_environ=env, @@ -504,17 +558,20 @@ class TestGroupSearch(helpers.FunctionalTestBase): def setup(self): super(TestGroupSearch, self).setup() - self.app = self._get_test_app() factories.Group(name='grp-one', title='AGrp One') factories.Group(name='grp-two', title='AGrp Two') factories.Group(name='grp-three', title='Grp Three') - self.search_url = url_for(controller='group', action='index') + + app = self._get_test_app() + with app.flask_app.test_request_context(): + self.search_url = url_for(controller='group', action='index') def test_group_search(self): '''Requesting group search (index) returns list of groups and search form.''' - index_response = self.app.get(self.search_url) + app = self._get_test_app() + index_response = app.get(self.search_url) index_response_html = BeautifulSoup(index_response.body) grp_names = index_response_html.select('ul.media-grid ' 'li.media-item ' @@ -529,7 +586,8 @@ def test_group_search(self): def test_group_search_results(self): '''Searching via group search form returns list of expected groups.''' - index_response = self.app.get(self.search_url) + app = self._get_test_app() + index_response = app.get(self.search_url) search_form = index_response.forms['group-search-form'] search_form['q'] = 'AGrp' search_response = webtest_submit(search_form) @@ -548,7 +606,8 @@ def test_group_search_results(self): def test_group_search_no_results(self): '''Searching with a term that doesn't apply returns no results.''' - index_response = self.app.get(self.search_url) + app = self._get_test_app() + index_response = app.get(self.search_url) search_form = index_response.forms['group-search-form'] search_form['q'] = 'No Results Here' search_response = webtest_submit(search_form) @@ -580,8 +639,9 @@ def test_group_search_within_org(self): factories.Dataset(name="ds-three", title="Dataset Three", groups=[{'id': grp['id']}]) - grp_url = url_for(controller='group', action='read', - id=grp['id']) + with app.flask_app.test_request_context(): + grp_url = url_for(controller='group', action='read', + id=grp['id']) grp_response = app.get(grp_url) grp_response_html = BeautifulSoup(grp_response.body) @@ -608,8 +668,9 @@ def test_group_search_within_org_results(self): factories.Dataset(name="ds-three", title="Dataset Three", groups=[{'id': grp['id']}]) - grp_url = url_for(controller='group', action='read', - id=grp['id']) + with app.flask_app.test_request_context(): + grp_url = url_for(controller='group', action='read', + id=grp['id']) grp_response = app.get(grp_url) search_form = grp_response.forms['group-datasets-search-form'] search_form['q'] = 'One' @@ -641,8 +702,9 @@ def test_group_search_within_org_no_results(self): factories.Dataset(name="ds-three", title="Dataset Three", groups=[{'id': grp['id']}]) - grp_url = url_for(controller='group', action='read', - id=grp['id']) + with app.flask_app.test_request_context(): + grp_url = url_for(controller='group', action='read', + id=grp['id']) grp_response = app.get(grp_url) search_form = grp_response.forms['group-datasets-search-form'] search_form['q'] = 'Nout' @@ -671,8 +733,9 @@ def test_group_index(self): name='test-group-{0}'.format(_i), title='Test Group {0}'.format(_i)) - url = url_for(controller='group', - action='index') + with app.flask_app.test_request_context(): + url = url_for(controller='group', + action='index') response = app.get(url) for i in xrange(1, 22): @@ -681,9 +744,10 @@ def test_group_index(self): assert 'Test Group 22' not in response - url = url_for(controller='group', - action='index', - page=1) + with app.flask_app.test_request_context(): + url = url_for(controller='group', + action='index', + page=1) response = app.get(url) for i in xrange(1, 22): @@ -692,9 +756,10 @@ def test_group_index(self): assert 'Test Group 22' not in response - url = url_for(controller='group', - action='index', - page=2) + with app.flask_app.test_request_context(): + url = url_for(controller='group', + action='index', + page=2) response = app.get(url) for i in xrange(22, 26): diff --git a/ckan/tests/controllers/test_home.py b/ckan/tests/controllers/test_home.py index 44731868635..34c02739840 100644 --- a/ckan/tests/controllers/test_home.py +++ b/ckan/tests/controllers/test_home.py @@ -12,7 +12,11 @@ class TestHome(helpers.FunctionalTestBase): def test_home_renders(self): app = self._get_test_app() - response = app.get(url_for('home')) + + with app.flask_app.test_request_context(): + url = url_for('home') + + response = app.get(url) assert 'Welcome to CKAN' in response.body def test_template_head_end(self): @@ -20,14 +24,22 @@ def test_template_head_end(self): # test-core.ini sets ckan.template_head_end to this: test_link = '' - response = app.get(url_for('home')) + + with app.flask_app.test_request_context(): + url = url_for('home') + + response = app.get(url) assert test_link in response.body def test_template_footer_end(self): app = self._get_test_app() # test-core.ini sets ckan.template_footer_end to this: test_html = 'TEST TEMPLATE_FOOTER_END TEST' - response = app.get(url_for('home')) + + with app.flask_app.test_request_context(): + url = url_for('home') + + response = app.get(url) assert test_html in response.body def test_email_address_nag(self): @@ -41,10 +53,14 @@ def test_email_address_nag(self): model.Session.commit() env = {'REMOTE_USER': user.name.encode('ascii')} - response = app.get(url=url_for('home'), extra_environ=env) + with app.flask_app.test_request_context(): + url = url_for('home') + user_edit_url = url_for(controller='user', action='edit') + + response = app.get(url, extra_environ=env) assert 'update your profile' in response.body - assert url_for(controller='user', action='edit') in response.body + assert user_edit_url in response.body assert ' and add your email address.' in response.body def test_email_address_no_nag(self): @@ -52,7 +68,10 @@ def test_email_address_no_nag(self): user = factories.User(email='filled_in@nicely.com') env = {'REMOTE_USER': user['name'].encode('ascii')} - response = app.get(url=url_for('home'), extra_environ=env) + with app.flask_app.test_request_context(): + url = url_for('home') + + response = app.get(url, extra_environ=env) assert 'add your email address' not in response @@ -61,7 +80,11 @@ class TestI18nURLs(helpers.FunctionalTestBase): def test_right_urls_are_rendered_on_language_selector(self): app = self._get_test_app() - response = app.get(url_for('home')) + + with app.flask_app.test_request_context(): + url = url_for('home') + + response = app.get(url) html = BeautifulSoup(response.body) select = html.find(id='field-lang-select') @@ -77,7 +100,11 @@ def test_right_urls_are_rendered_on_language_selector(self): def test_default_english_option_is_selected_on_language_selector(self): app = self._get_test_app() - response = app.get(url_for('home')) + + with app.flask_app.test_request_context(): + url = url_for('home') + + response = app.get(url) html = BeautifulSoup(response.body) select = html.find(id='field-lang-select') @@ -89,7 +116,11 @@ def test_default_english_option_is_selected_on_language_selector(self): def test_right_option_is_selected_on_language_selector(self): app = self._get_test_app() - response = app.get(url_for('home', locale='ca')) + + with app.flask_app.test_request_context(): + url = url_for('home', locale='ca') + + response = app.get(url) html = BeautifulSoup(response.body) select = html.find(id='field-lang-select') diff --git a/ckan/tests/controllers/test_organization.py b/ckan/tests/controllers/test_organization.py index ed8da4a48a8..65db01c9f6f 100644 --- a/ckan/tests/controllers/test_organization.py +++ b/ckan/tests/controllers/test_organization.py @@ -1,8 +1,8 @@ # encoding: utf-8 from bs4 import BeautifulSoup +from ckan.lib.helpers import url_for from nose.tools import assert_equal, assert_true, assert_in -from routes import url_for from mock import patch from ckan.tests import factories, helpers @@ -12,19 +12,29 @@ class TestOrganizationNew(helpers.FunctionalTestBase): def setup(self): super(TestOrganizationNew, self).setup() - self.app = helpers._get_test_app() + self.user = factories.User() self.user_env = {'REMOTE_USER': self.user['name'].encode('ascii')} - self.organization_new_url = url_for(controller='organization', - action='new') + + app = helpers._get_test_app() + with app.flask_app.test_request_context(): + self.organization_new_url = url_for(controller='organization', + action='new') def test_not_logged_in(self): - self.app.get(url=url_for(controller='group', action='new'), - status=403) + + app = helpers._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='group', action='new') + app.get(url, status=403) def test_name_required(self): - response = self.app.get(url=self.organization_new_url, - extra_environ=self.user_env) + + app = helpers._get_test_app() + + response = app.get(url=self.organization_new_url, + extra_environ=self.user_env) form = response.forms['organization-edit-form'] response = webtest_submit(form, name='save', extra_environ=self.user_env) @@ -33,13 +43,16 @@ def test_name_required(self): assert_true('Name: Missing value' in response) def test_saved(self): - response = self.app.get(url=self.organization_new_url, - extra_environ=self.user_env) + + app = helpers._get_test_app() + + response = app.get(url=self.organization_new_url, + extra_environ=self.user_env) form = response.forms['organization-edit-form'] form['name'] = u'saved' - response = submit_and_follow(self.app, form, name='save', + response = submit_and_follow(app, form, name='save', extra_environ=self.user_env) group = helpers.call_action('organization_show', id='saved') assert_equal(group['title'], u'') @@ -47,6 +60,7 @@ def test_saved(self): assert_equal(group['state'], 'active') def test_all_fields_saved(self): + app = helpers._get_test_app() response = app.get(url=self.organization_new_url, extra_environ=self.user_env) @@ -57,7 +71,7 @@ def test_all_fields_saved(self): form['description'] = 'Sciencey datasets' form['image_url'] = 'http://example.com/image.png' - response = submit_and_follow(self.app, form, name='save', + response = submit_and_follow(app, form, name='save', extra_environ=self.user_env) group = helpers.call_action('organization_show', id='all-fields-saved') assert_equal(group['title'], u'Science') @@ -67,33 +81,44 @@ def test_all_fields_saved(self): class TestOrganizationList(helpers.FunctionalTestBase): def setup(self): super(TestOrganizationList, self).setup() - self.app = helpers._get_test_app() + self.user = factories.User() self.user_env = {'REMOTE_USER': self.user['name'].encode('ascii')} - self.organization_list_url = url_for(controller='organization', - action='index') + app = helpers._get_test_app() + with app.flask_app.test_request_context(): + self.organization_list_url = url_for(controller='organization', + action='index') + + @patch('ckan.logic.auth.get.organization_list', + return_value={'success': False}) + def test_error_message_shown_when_no_organization_list_permission( + self, mock_check_access): - @patch('ckan.logic.auth.get.organization_list', return_value={'success': False}) - def test_error_message_shown_when_no_organization_list_permission(self, mock_check_access): - response = self.app.get(url=self.organization_list_url, - extra_environ=self.user_env, - status=403) + app = helpers._get_test_app() + + app.get(url=self.organization_list_url, + extra_environ=self.user_env, + status=403) class TestOrganizationRead(helpers.FunctionalTestBase): def setup(self): super(TestOrganizationRead, self).setup() - self.app = helpers._get_test_app() + self.user = factories.User() self.user_env = {'REMOTE_USER': self.user['name'].encode('ascii')} self.organization = factories.Organization(user=self.user) def test_organization_read(self): - response = self.app.get(url=url_for(controller='organization', - action='read', - id=self.organization['id']), - status=200, - extra_environ=self.user_env) + + app = helpers._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='organization', action='read', + id=self.organization['id']) + response = app.get(url=url, + status=200, + extra_environ=self.user_env) assert_in(self.organization['title'], response) assert_in(self.organization['description'], response) @@ -101,24 +126,33 @@ def test_organization_read(self): class TestOrganizationEdit(helpers.FunctionalTestBase): def setup(self): super(TestOrganizationEdit, self).setup() - self.app = helpers._get_test_app() + self.user = factories.User() self.user_env = {'REMOTE_USER': self.user['name'].encode('ascii')} self.organization = factories.Organization(user=self.user) - self.organization_edit_url = url_for(controller='organization', - action='edit', - id=self.organization['id']) + app = helpers._get_test_app() + with app.flask_app.test_request_context(): + self.organization_edit_url = url_for(controller='organization', + action='edit', + id=self.organization['id']) def test_group_doesnt_exist(self): - url = url_for(controller='organization', - action='edit', - id='doesnt_exist') - self.app.get(url=url, extra_environ=self.user_env, - status=404) + + app = helpers._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='organization', + action='edit', + id='doesnt_exist') + app.get(url=url, extra_environ=self.user_env, + status=404) def test_saved(self): - response = self.app.get(url=self.organization_edit_url, - extra_environ=self.user_env) + + app = helpers._get_test_app() + + response = app.get(url=self.organization_edit_url, + extra_environ=self.user_env) form = response.forms['organization-edit-form'] response = webtest_submit(form, name='save', @@ -130,8 +164,11 @@ def test_saved(self): assert_equal(group['state'], 'active') def test_all_fields_saved(self): - response = self.app.get(url=self.organization_edit_url, - extra_environ=self.user_env) + + app = helpers._get_test_app() + + response = app.get(url=self.organization_edit_url, + extra_environ=self.user_env) form = response.forms['organization-edit-form'] form['name'] = u'all-fields-edited' @@ -151,59 +188,79 @@ def test_all_fields_saved(self): class TestOrganizationDelete(helpers.FunctionalTestBase): def setup(self): super(TestOrganizationDelete, self).setup() - self.app = helpers._get_test_app() + self.user = factories.User() self.user_env = {'REMOTE_USER': self.user['name'].encode('ascii')} self.organization = factories.Organization(user=self.user) def test_owner_delete(self): - response = self.app.get(url=url_for(controller='organization', - action='delete', - id=self.organization['id']), - status=200, - extra_environ=self.user_env) + + app = helpers._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='organization', + action='delete', + id=self.organization['id']) + response = app.get(url, status=200, extra_environ=self.user_env) form = response.forms['organization-confirm-delete-form'] - response = submit_and_follow(self.app, form, name='delete', + response = submit_and_follow(app, form, name='delete', extra_environ=self.user_env) organization = helpers.call_action('organization_show', id=self.organization['id']) assert_equal(organization['state'], 'deleted') def test_sysadmin_delete(self): + + app = helpers._get_test_app() + sysadmin = factories.Sysadmin() extra_environ = {'REMOTE_USER': sysadmin['name'].encode('ascii')} - response = self.app.get(url=url_for(controller='organization', - action='delete', - id=self.organization['id']), - status=200, - extra_environ=extra_environ) + with app.flask_app.test_request_context(): + url = url_for(controller='organization', + action='delete', + id=self.organization['id']) + + response = app.get(url=url, + status=200, + extra_environ=extra_environ) form = response.forms['organization-confirm-delete-form'] - response = submit_and_follow(self.app, form, name='delete', + response = submit_and_follow(app, form, name='delete', extra_environ=self.user_env) organization = helpers.call_action('organization_show', id=self.organization['id']) assert_equal(organization['state'], 'deleted') def test_non_authorized_user_trying_to_delete_fails(self): + + app = helpers._get_test_app() + user = factories.User() extra_environ = {'REMOTE_USER': user['name'].encode('ascii')} - self.app.get(url=url_for(controller='organization', - action='delete', - id=self.organization['id']), - status=403, - extra_environ=extra_environ) + with app.flask_app.test_request_context(): + url = url_for(controller='organization', + action='delete', + id=self.organization['id']) + + app.get(url=url, + status=403, + extra_environ=extra_environ) organization = helpers.call_action('organization_show', id=self.organization['id']) assert_equal(organization['state'], 'active') def test_anon_user_trying_to_delete_fails(self): - self.app.get(url=url_for(controller='organization', - action='delete', - id=self.organization['id']), - status=403) + + app = helpers._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='organization', + action='delete', + id=self.organization['id']) + + app.get(url=url, + status=403) organization = helpers.call_action('organization_show', id=self.organization['id']) @@ -213,19 +270,24 @@ def test_anon_user_trying_to_delete_fails(self): class TestOrganizationBulkProcess(helpers.FunctionalTestBase): def setup(self): super(TestOrganizationBulkProcess, self).setup() - self.app = helpers._get_test_app() + self.user = factories.User() self.user_env = {'REMOTE_USER': self.user['name'].encode('ascii')} self.organization = factories.Organization(user=self.user) - self.organization_bulk_url = url_for(controller='organization', - action='bulk_process', - id=self.organization['id']) + app = helpers._get_test_app() + with app.flask_app.test_request_context(): + self.organization_bulk_url = url_for(controller='organization', + action='bulk_process', + id=self.organization['id']) def test_make_private(self): + + app = helpers._get_test_app() + datasets = [factories.Dataset(owner_org=self.organization['id']) for i in range(0, 5)] - response = self.app.get(url=self.organization_bulk_url, - extra_environ=self.user_env) + response = app.get(url=self.organization_bulk_url, + extra_environ=self.user_env) form = response.forms[1] for v in form.fields.values(): try: @@ -241,11 +303,14 @@ def test_make_private(self): assert_equal(d['private'], True) def test_make_public(self): + + app = helpers._get_test_app() + datasets = [factories.Dataset(owner_org=self.organization['id'], private=True) for i in range(0, 5)] - response = self.app.get(url=self.organization_bulk_url, - extra_environ=self.user_env) + response = app.get(url=self.organization_bulk_url, + extra_environ=self.user_env) form = response.forms[1] for v in form.fields.values(): try: @@ -261,11 +326,14 @@ def test_make_public(self): assert_equal(d['private'], False) def test_delete(self): + + app = helpers._get_test_app() + datasets = [factories.Dataset(owner_org=self.organization['id'], private=True) for i in range(0, 5)] - response = self.app.get(url=self.organization_bulk_url, - extra_environ=self.user_env) + response = app.get(url=self.organization_bulk_url, + extra_environ=self.user_env) form = response.forms[1] for v in form.fields.values(): try: @@ -287,17 +355,23 @@ class TestOrganizationSearch(helpers.FunctionalTestBase): def setup(self): super(TestOrganizationSearch, self).setup() - self.app = self._get_test_app() factories.Organization(name='org-one', title='AOrg One') factories.Organization(name='org-two', title='AOrg Two') factories.Organization(name='org-three', title='Org Three') - self.search_url = url_for(controller='organization', action='index') + + app = helpers._get_test_app() + with app.flask_app.test_request_context(): + self.search_url = url_for(controller='organization', + action='index') def test_organization_search(self): + + app = helpers._get_test_app() + '''Requesting organization search (index) returns list of organizations and search form.''' - index_response = self.app.get(self.search_url) + index_response = app.get(self.search_url) index_response_html = BeautifulSoup(index_response.body) org_names = index_response_html.select('ul.media-grid ' 'li.media-item ' @@ -310,10 +384,13 @@ def test_organization_search(self): assert_true('Org Three' in org_names) def test_organization_search_results(self): + + app = helpers._get_test_app() + '''Searching via organization search form returns list of expected organizations.''' - index_response = self.app.get(self.search_url) + index_response = app.get(self.search_url) search_form = index_response.forms['organization-search-form'] search_form['q'] = 'AOrg' search_response = webtest_submit(search_form) @@ -330,9 +407,12 @@ def test_organization_search_results(self): assert_true('Org Three' not in org_names) def test_organization_search_no_results(self): + + app = helpers._get_test_app() + '''Searching with a term that doesn't apply returns no results.''' - index_response = self.app.get(self.search_url) + index_response = app.get(self.search_url) search_form = index_response.forms['organization-search-form'] search_form['q'] = 'No Results Here' search_response = webtest_submit(search_form) @@ -365,8 +445,9 @@ def test_organization_search_within_org(self): factories.Dataset(name="ds-three", title="Dataset Three", owner_org=org['id']) - org_url = url_for(controller='organization', action='read', - id=org['id']) + with app.flask_app.test_request_context(): + org_url = url_for(controller='organization', action='read', + id=org['id']) org_response = app.get(org_url) org_response_html = BeautifulSoup(org_response.body) @@ -394,8 +475,9 @@ def test_organization_search_within_org_results(self): factories.Dataset(name="ds-three", title="Dataset Three", owner_org=org['id']) - org_url = url_for(controller='organization', action='read', - id=org['id']) + with app.flask_app.test_request_context(): + org_url = url_for(controller='organization', action='read', + id=org['id']) org_response = app.get(org_url) search_form = org_response.forms['organization-datasets-search-form'] search_form['q'] = 'One' @@ -427,8 +509,9 @@ def test_organization_search_within_org_no_results(self): factories.Dataset(name="ds-three", title="Dataset Three", owner_org=org['id']) - org_url = url_for(controller='organization', action='read', - id=org['id']) + with app.flask_app.test_request_context(): + org_url = url_for(controller='organization', action='read', + id=org['id']) org_response = app.get(org_url) search_form = org_response.forms['organization-datasets-search-form'] search_form['q'] = 'Nout' diff --git a/ckan/tests/controllers/test_package.py b/ckan/tests/controllers/test_package.py index d4cc8b379ed..6489d7fe33f 100644 --- a/ckan/tests/controllers/test_package.py +++ b/ckan/tests/controllers/test_package.py @@ -9,12 +9,10 @@ assert_in ) -from mock import patch, MagicMock -from routes import url_for +from ckan.lib.helpers import url_for import ckan.model as model import ckan.plugins as p -from ckan.lib import search import ckan.tests.helpers as helpers import ckan.tests.factories as factories @@ -27,8 +25,10 @@ def _get_package_new_page(app): user = factories.User() env = {'REMOTE_USER': user['name'].encode('ascii')} + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='new') response = app.get( - url=url_for(controller='package', action='new'), + url=url, extra_environ=env, ) return env, response @@ -50,12 +50,18 @@ def test_needs_organization_but_no_organizations_has_button(self): sysadmin = factories.Sysadmin() env = {'REMOTE_USER': sysadmin['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='new') + response = app.get( - url=url_for(controller='package', action='new'), + url=url, extra_environ=env ) assert 'dataset-edit' not in response.forms - assert url_for(controller='organization', action='new') in response + + with app.flask_app.test_request_context(): + assert url_for(controller='organization', action='new') in response @helpers.mock_auth('ckan.logic.auth.create.package_create') @helpers.change_config('ckan.auth.create_unowned_dataset', 'false') @@ -73,13 +79,19 @@ def test_needs_organization_but_no_organizations_no_button(self, user = factories.User() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='new') + response = app.get( - url=url_for(controller='package', action='new'), + url=url, extra_environ=env ) assert 'dataset-edit' not in response.forms - assert url_for(controller='organization', action='new') not in response + + with app.flask_app.test_request_context(): + assert url_for(controller='organization', action='new') not in response assert 'Ask a system administrator' in response def test_name_required(self): @@ -240,8 +252,11 @@ def test_dataset_edit_org_dropdown_visible_to_normal_user_with_orgs_available(se app = self._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='new') response = app.get( - url=url_for(controller='package', action='new'), + url=url, extra_environ=env, ) @@ -262,9 +277,11 @@ def test_dataset_edit_org_dropdown_visible_to_normal_user_with_orgs_available(se assert_equal(pkg.state, 'active') # edit package page response - url = url_for(controller='package', - action='edit', - id=pkg.id) + + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id=pkg.id) pkg_edit_response = app.get(url=url, extra_environ=env) # A field with the correct id is in the response form = pkg_edit_response.forms['dataset-edit'] @@ -285,8 +302,10 @@ def test_dataset_edit_org_dropdown_normal_user_can_remove_org(self): app = self._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='new') response = app.get( - url=url_for(controller='package', action='new'), + url=url, extra_environ=env, ) @@ -306,9 +325,10 @@ def test_dataset_edit_org_dropdown_normal_user_can_remove_org(self): assert_not_equal(pkg.owner_org, None) # edit package page response - url = url_for(controller='package', - action='edit', - id=pkg.id) + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id=pkg.id) pkg_edit_response = app.get(url=url, extra_environ=env) # edit dataset @@ -331,8 +351,11 @@ def test_dataset_edit_org_dropdown_not_visible_to_normal_user_with_no_orgs_avail app = self._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='new') response = app.get( - url=url_for(controller='package', action='new'), + url=url, extra_environ=env, ) @@ -352,9 +375,10 @@ def test_dataset_edit_org_dropdown_not_visible_to_normal_user_with_no_orgs_avail assert_equal(pkg.state, 'active') # edit package response - url = url_for(controller='package', - action='edit', - id=model.Package.by_name(u'my-dataset').id) + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id=model.Package.by_name(u'my-dataset').id) pkg_edit_response = app.get(url=url, extra_environ=env) # A field with the correct id is in the response form = pkg_edit_response.forms['dataset-edit'] @@ -376,8 +400,10 @@ def test_dataset_edit_org_dropdown_visible_to_sysadmin_with_no_orgs_available(se app = self._get_test_app() # user in env is sysadmin env = {'REMOTE_USER': sysadmin['name'].encode('ascii')} + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='new') response = app.get( - url=url_for(controller='package', action='new'), + url=url, extra_environ=env, ) @@ -398,9 +424,10 @@ def test_dataset_edit_org_dropdown_visible_to_sysadmin_with_no_orgs_available(se assert_equal(pkg.state, 'active') # edit package page response - url = url_for(controller='package', - action='edit', - id=pkg.id) + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id=pkg.id) pkg_edit_response = app.get(url=url, extra_environ=env) # A field with the correct id is in the response assert 'id="field-organizations"' in pkg_edit_response @@ -410,11 +437,14 @@ def test_dataset_edit_org_dropdown_visible_to_sysadmin_with_no_orgs_available(se def test_unauthed_user_creating_dataset(self): app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='new') # provide REMOTE_ADDR to idenfity as remote user, see # ckan.views.identify_user() for details - response = app.post(url=url_for(controller='package', action='new'), - extra_environ={'REMOTE_ADDR': '127.0.0.1'}, - status=403) + + app.post(url=url, + extra_environ={'REMOTE_ADDR': '127.0.0.1'}, + status=403) class TestPackageEdit(helpers.FunctionalTestBase): @@ -426,10 +456,13 @@ def test_organization_admin_can_edit(self): dataset = factories.Dataset(owner_org=organization['id']) app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id=dataset['name']) response = app.get( - url_for(controller='package', - action='edit', - id=dataset['name']), + url, extra_environ=env, ) form = response.forms['dataset-edit'] @@ -447,10 +480,12 @@ def test_organization_editor_can_edit(self): dataset = factories.Dataset(owner_org=organization['id']) app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id=dataset['name']) response = app.get( - url_for(controller='package', - action='edit', - id=dataset['name']), + url, extra_environ=env, ) form = response.forms['dataset-edit'] @@ -468,10 +503,12 @@ def test_organization_member_cannot_edit(self): dataset = factories.Dataset(owner_org=organization['id']) app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} - response = app.get( - url_for(controller='package', - action='edit', - id=dataset['name']), + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id=dataset['name']) + app.get( + url, extra_environ=env, status=403, ) @@ -482,19 +519,20 @@ def test_user_not_in_organization_cannot_edit(self): dataset = factories.Dataset(owner_org=organization['id']) app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} - response = app.get( - url_for(controller='package', - action='edit', - id=dataset['name']), + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id=dataset['name']) + app.get( + url, extra_environ=env, status=403, ) env = {'REMOTE_USER': user['name'].encode('ascii')} - response = app.post( - url_for(controller='package', - action='edit', - id=dataset['name']), + + app.post( + url, {'notes': 'edited description'}, extra_environ=env, status=403, @@ -504,17 +542,17 @@ def test_anonymous_user_cannot_edit(self): organization = factories.Organization() dataset = factories.Dataset(owner_org=organization['id']) app = helpers._get_test_app() - response = app.get( - url_for(controller='package', - action='edit', - id=dataset['name']), + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id=dataset['name']) + app.get( + url, status=403, ) - response = app.post( - url_for(controller='package', - action='edit', - id=dataset['name']), + app.post( + url, {'notes': 'edited description'}, status=403, ) @@ -528,10 +566,13 @@ def test_validation_errors_for_dataset_name_appear(self): dataset = factories.Dataset(owner_org=organization['id']) app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id=dataset['name']) + response = app.get( - url_for(controller='package', - action='edit', - id=dataset['name']), + url, extra_environ=env, ) form = response.forms['dataset-edit'] @@ -546,10 +587,13 @@ def test_edit_a_dataset_that_does_not_exist_404s(self): user = factories.User() app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='edit', + id='does-not-exist') + response = app.get( - url_for(controller='package', - action='edit', - id='does-not-exist'), + url, extra_environ=env, expect_errors=True ) @@ -560,8 +604,11 @@ class TestPackageRead(helpers.FunctionalTestBase): def test_read(self): dataset = factories.Dataset() app = helpers._get_test_app() - response = app.get(url_for(controller='package', action='read', - id=dataset['name'])) + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='read', + id=dataset['name']) + response = app.get(url) response.mustcontain('Test Dataset') response.mustcontain('Just another test dataset') @@ -585,13 +632,13 @@ def test_organization_members_can_read_private_datasets(self): ) app = helpers._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='read', + id=dataset['name']) for user, user_dict in members.items(): response = app.get( - url_for( - controller='package', - action='read', - id=dataset['name'] - ), + url, extra_environ={ 'REMOTE_USER': user_dict['name'].encode('ascii'), }, @@ -606,8 +653,13 @@ def test_anonymous_users_cannot_read_private_datasets(self): private=True, ) app = helpers._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='read', + id=dataset['name']) + response = app.get( - url_for(controller='package', action='read', id=dataset['name']), + url, status=404 ) assert_equal(404, response.status_int) @@ -620,8 +672,13 @@ def test_user_not_in_organization_cannot_read_private_datasets(self): private=True, ) app = helpers._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='read', + id=dataset['name']) + response = app.get( - url_for(controller='package', action='read', id=dataset['name']), + url, extra_environ={'REMOTE_USER': user['name'].encode('ascii')}, status=404 ) @@ -631,18 +688,20 @@ def test_read_rdf(self): ''' The RDF outputs now live in ckanext-dcat''' dataset1 = factories.Dataset() - offset = url_for(controller='package', action='read', - id=dataset1['name']) + ".rdf" app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='package', action='read', + id=dataset1['name']) + ".rdf" app.get(offset, status=404) def test_read_n3(self): ''' The RDF outputs now live in ckanext-dcat''' dataset1 = factories.Dataset() - offset = url_for(controller='package', action='read', - id=dataset1['name']) + ".n3" app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='package', action='read', + id=dataset1['name']) + ".n3" app.get(offset, status=404) @@ -656,8 +715,12 @@ def test_owner_delete(self): app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='delete', id=dataset['name']) + response = app.post( - url_for(controller='package', action='delete', id=dataset['name']), + url, extra_environ=env, ) response = response.follow() @@ -668,9 +731,13 @@ def test_owner_delete(self): def test_delete_on_non_existing_dataset(self): app = helpers._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='delete', + id='schrodingersdatset') + response = app.post( - url_for(controller='package', action='delete', - id='schrodingersdatset'), + url, expect_errors=True, ) assert_equal(404, response.status_int) @@ -683,8 +750,11 @@ def test_sysadmin_can_delete_any_dataset(self): user = factories.Sysadmin() env = {'REMOTE_USER': user['name'].encode('ascii')} + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='delete', id=dataset['name']) + response = app.post( - url_for(controller='package', action='delete', id=dataset['name']), + url, extra_environ=env, ) response = response.follow() @@ -701,8 +771,12 @@ def test_anon_user_cannot_delete_owned_dataset(self): dataset = factories.Dataset(owner_org=owner_org['id']) app = helpers._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='delete', id=dataset['name']) + response = app.post( - url_for(controller='package', action='delete', id=dataset['name']), + url, status=403, ) response.mustcontain('Unauthorized to delete package') @@ -720,8 +794,12 @@ def test_logged_in_user_cannot_delete_owned_dataset(self): app = helpers._get_test_app() user = factories.User() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='delete', id=dataset['name']) + response = app.post( - url_for(controller='package', action='delete', id=dataset['name']), + url, extra_environ=env, expect_errors=True ) @@ -741,8 +819,12 @@ def test_confirm_cancel_delete(self): app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='delete', id=dataset['name']) + response = app.get( - url_for(controller='package', action='delete', id=dataset['name']), + url, extra_environ=env, ) assert_equal(200, response.status_int) @@ -766,12 +848,16 @@ def test_manage_dataset_resource_listing_page(self): resource = factories.Resource(package_id=dataset['id']) app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} - response = app.get( - url_for( + + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='resources', id=dataset['name'], - ), + ) + + response = app.get( + url, extra_environ=env ) assert_in(resource['name'], response) @@ -785,12 +871,16 @@ def test_unauth_user_cannot_view_manage_dataset_resource_listing_page(self): resource = factories.Resource(package_id=dataset['id']) app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} - response = app.get( - url_for( + + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='resources', id=dataset['name'], - ), + ) + + response = app.get( + url, extra_environ=env ) assert_in(resource['name'], response) @@ -801,12 +891,16 @@ def test_404_on_manage_dataset_resource_listing_page_that_does_not_exist(self): user = factories.User() app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} - response = app.get( - url_for( + + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='resources', id='does-not-exist' - ), + ) + + response = app.get( + url, extra_environ=env, expect_errors=True ) @@ -818,12 +912,15 @@ def test_add_new_resource_with_link_and_download(self): env = {'REMOTE_USER': user['name'].encode('ascii')} app = helpers._get_test_app() - response = app.get( - url_for( + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='new_resource', id=dataset['id'], - ), + ) + + response = app.get( + url, extra_environ=env ) @@ -833,13 +930,17 @@ def test_add_new_resource_with_link_and_download(self): 'go-dataset-complete') result = helpers.call_action('package_show', id=dataset['id']) - response = app.get( - url_for( + + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='resource_download', id=dataset['id'], resource_id=result['resources'][0]['id'] - ), + ) + + response = app.get( + url, extra_environ=env, ) assert_equal(302, response.status_int) @@ -855,12 +956,15 @@ def test_editor_can_add_new_resource(self): env = {'REMOTE_USER': user['name'].encode('ascii')} app = helpers._get_test_app() - response = app.get( - url_for( + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='new_resource', id=dataset['id'], - ), + ) + + response = app.get( + url, extra_environ=env ) @@ -885,12 +989,15 @@ def test_admin_can_add_new_resource(self): env = {'REMOTE_USER': user['name'].encode('ascii')} app = helpers._get_test_app() - response = app.get( - url_for( + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='new_resource', id=dataset['id'], - ), + ) + + response = app.get( + url, extra_environ=env ) @@ -915,22 +1022,28 @@ def test_member_cannot_add_new_resource(self): env = {'REMOTE_USER': user['name'].encode('ascii')} app = helpers._get_test_app() - response = app.get( - url_for( + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='new_resource', id=dataset['id'], - ), + ) + + response = app.get( + url, extra_environ=env, status=403, ) - response = app.post( - url_for( + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='new_resource', id=dataset['id'], - ), + ) + + response = app.post( + url, {'name': 'test', 'url': 'test', 'save': 'save', 'id': ''}, extra_environ=env, status=403, @@ -946,22 +1059,28 @@ def test_non_organization_users_cannot_add_new_resource(self): env = {'REMOTE_USER': user['name'].encode('ascii')} app = helpers._get_test_app() - response = app.get( - url_for( + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='new_resource', id=dataset['id'], - ), + ) + + response = app.get( + url, extra_environ=env, status=403, ) - response = app.post( - url_for( + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='new_resource', id=dataset['id'], - ), + ) + + response = app.post( + url, {'name': 'test', 'url': 'test', 'save': 'save', 'id': ''}, extra_environ=env, status=403, @@ -974,21 +1093,27 @@ def test_anonymous_users_cannot_add_new_resource(self): ) app = helpers._get_test_app() - response = app.get( - url_for( + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='new_resource', id=dataset['id'], - ), + ) + + response = app.get( + url, status=403, ) - response = app.post( - url_for( + with app.flask_app.test_request_context(): + url = url_for( controller='package', action='new_resource', id=dataset['id'], - ), + ) + + response = app.post( + url, {'name': 'test', 'url': 'test', 'save': 'save', 'id': ''}, status=403, ) @@ -1011,35 +1136,41 @@ def teardown_class(cls): def test_existent_resource_view_page_returns_ok_code(self): resource_view = factories.ResourceView() - url = url_for(controller='package', - action='resource_read', - id=resource_view['package_id'], - resource_id=resource_view['resource_id'], - view_id=resource_view['id']) - app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='resource_read', + id=resource_view['package_id'], + resource_id=resource_view['resource_id'], + view_id=resource_view['id']) + app.get(url, status=200) def test_inexistent_resource_view_page_returns_not_found_code(self): resource_view = factories.ResourceView() - url = url_for(controller='package', - action='resource_read', - id=resource_view['package_id'], - resource_id=resource_view['resource_id'], - view_id='inexistent-view-id') - app = self._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='resource_read', + id=resource_view['package_id'], + resource_id=resource_view['resource_id'], + view_id='inexistent-view-id') + app.get(url, status=404) def test_resource_view_description_is_rendered_as_markdown(self): resource_view = factories.ResourceView(description="Some **Markdown**") - url = url_for(controller='package', - action='resource_read', - id=resource_view['package_id'], - resource_id=resource_view['resource_id'], - view_id=resource_view['id']) + app = self._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='resource_read', + id=resource_view['package_id'], + resource_id=resource_view['resource_id'], + view_id=resource_view['id']) response = app.get(url) response.mustcontain('Some Markdown') @@ -1050,12 +1181,12 @@ def test_existing_resource_with_not_associated_dataset(self): dataset = factories.Dataset() resource = factories.Resource() - url = url_for(controller='package', - action='resource_read', - id=dataset['id'], - resource_id=resource['id']) - app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='resource_read', + id=dataset['id'], + resource_id=resource['id']) app.get(url, status=404) def test_resource_read_logged_in_user(self): @@ -1067,12 +1198,12 @@ def test_resource_read_logged_in_user(self): dataset = factories.Dataset() resource = factories.Resource(package_id=dataset['id']) - url = url_for(controller='package', - action='resource_read', - id=dataset['id'], - resource_id=resource['id']) - app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='resource_read', + id=dataset['id'], + resource_id=resource['id']) app.get(url, status=200, extra_environ=env) def test_resource_read_anon_user(self): @@ -1082,12 +1213,12 @@ def test_resource_read_anon_user(self): dataset = factories.Dataset() resource = factories.Resource(package_id=dataset['id']) - url = url_for(controller='package', - action='resource_read', - id=dataset['id'], - resource_id=resource['id']) - app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='resource_read', + id=dataset['id'], + resource_id=resource['id']) app.get(url, status=200) def test_resource_read_sysadmin(self): @@ -1099,12 +1230,12 @@ def test_resource_read_sysadmin(self): dataset = factories.Dataset() resource = factories.Resource(package_id=dataset['id']) - url = url_for(controller='package', - action='resource_read', - id=dataset['id'], - resource_id=resource['id']) - app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='resource_read', + id=dataset['id'], + resource_id=resource['id']) app.get(url, status=200, extra_environ=env) def test_user_not_in_organization_cannot_read_private_dataset(self): @@ -1117,12 +1248,12 @@ def test_user_not_in_organization_cannot_read_private_dataset(self): ) resource = factories.Resource(package_id=dataset['id']) - url = url_for(controller='package', - action='resource_read', - id=dataset['id'], - resource_id=resource['id']) - app = self._get_test_app() + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='resource_read', + id=dataset['id'], + resource_id=resource['id']) response = app.get(url, status=404, extra_environ=env) @@ -1149,14 +1280,16 @@ def test_organization_members_can_read_resources_in_private_datasets(self): app = helpers._get_test_app() + with app.flask_app.test_request_context(): + url = url_for( + controller='package', + action='resource_read', + id=dataset['name'], + resource_id=resource['id'], + ) for user, user_dict in members.items(): response = app.get( - url_for( - controller='package', - action='resource_read', - id=dataset['name'], - resource_id=resource['id'], - ), + url, extra_environ={ 'REMOTE_USER': user_dict['name'].encode('ascii'), }, @@ -1170,8 +1303,12 @@ def test_anonymous_users_cannot_read_private_datasets(self): private=True, ) app = helpers._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='read', id=dataset['name']) + response = app.get( - url_for(controller='package', action='read', id=dataset['name']), + url, status=404 ) assert_equal(404, response.status_int) @@ -1187,9 +1324,13 @@ def test_dataset_owners_can_delete_resources(self): resource = factories.Resource(package_id=dataset['id']) app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='resource_delete', + id=dataset['name'], resource_id=resource['id']) + response = app.post( - url_for(controller='package', action='resource_delete', - id=dataset['name'], resource_id=resource['id']), + url, extra_environ=env, ) response = response.follow() @@ -1207,9 +1348,13 @@ def test_deleting_non_existing_resource_404s(self): dataset = factories.Dataset(owner_org=owner_org['id']) env = {'REMOTE_USER': user['name'].encode('ascii')} app = helpers._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='resource_delete', + id=dataset['name'], resource_id='doesnotexist') + response = app.post( - url_for(controller='package', action='resource_delete', - id=dataset['name'], resource_id='doesnotexist'), + url, extra_environ=env, expect_errors=True ) @@ -1224,9 +1369,13 @@ def test_anon_users_cannot_delete_owned_resources(self): resource = factories.Resource(package_id=dataset['id']) app = helpers._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='resource_delete', + id=dataset['name'], resource_id=resource['id']) + response = app.post( - url_for(controller='package', action='resource_delete', - id=dataset['name'], resource_id=resource['id']), + url, status=403, ) response.mustcontain('Unauthorized to delete package') @@ -1244,9 +1393,13 @@ def test_logged_in_users_cannot_delete_resources_they_do_not_own(self): user = factories.User() env = {'REMOTE_USER': user['name'].encode('ascii')} app = helpers._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='resource_delete', + id=dataset['name'], resource_id=resource['id']) + response = app.post( - url_for(controller='package', action='resource_delete', - id=dataset['name'], resource_id=resource['id']), + url, extra_environ=env, expect_errors=True ) @@ -1261,9 +1414,13 @@ def test_sysadmins_can_delete_any_resource(self): sysadmin = factories.Sysadmin() app = helpers._get_test_app() env = {'REMOTE_USER': sysadmin['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='resource_delete', + id=dataset['name'], resource_id=resource['id']) + response = app.post( - url_for(controller='package', action='resource_delete', - id=dataset['name'], resource_id=resource['id']), + url, extra_environ=env, ) response = response.follow() @@ -1286,9 +1443,13 @@ def test_confirm_and_cancel_deleting_a_resource(self): resource = factories.Resource(package_id=dataset['id']) app = helpers._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='package', action='resource_delete', + id=dataset['name'], resource_id=resource['id']) + response = app.get( - url_for(controller='package', action='resource_delete', - id=dataset['name'], resource_id=resource['id']), + url, extra_environ=env, ) assert_equal(200, response.status_int) @@ -1306,8 +1467,9 @@ class TestSearch(helpers.FunctionalTestBase): def test_search_basic(self): dataset1 = factories.Dataset() - offset = url_for(controller='package', action='search') app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='package', action='search') page = app.get(offset) assert dataset1['name'] in page.body.decode('utf8') @@ -1316,8 +1478,10 @@ def test_search_sort_by_blank(self): factories.Dataset() # ?sort has caused an exception in the past - offset = url_for(controller='package', action='search') + '?sort' + app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='package', action='search') + '?sort' app.get(offset) def test_search_sort_by_bad(self): @@ -1326,9 +1490,11 @@ def test_search_sort_by_bad(self): # bad spiders try all sorts of invalid values for sort. They should get # a 400 error with specific error message. No need to alert the # administrator. - offset = url_for(controller='package', action='search') + \ - '?sort=gvgyr_fgevat+nfp' + app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='package', action='search') + \ + '?sort=gvgyr_fgevat+nfp' response = app.get(offset, status=[200, 400]) if response.status == 200: import sys @@ -1344,9 +1510,10 @@ def test_search_solr_syntax_error(self): # Whilst this could be due to a bad user input, it could also be # because CKAN mangled things somehow and therefore we flag it up to # the administrator and give a meaningless error, just in case - offset = url_for(controller='package', action='search') + \ - '?q=--included' app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='package', action='search') + \ + '?q=--included' search_response = app.get(offset) search_response_html = BeautifulSoup(search_response.body) @@ -1357,8 +1524,9 @@ def test_search_solr_syntax_error(self): def test_search_plugin_hooks(self): with p.use_plugin('test_package_controller_plugin') as plugin: - offset = url_for(controller='package', action='search') app = self._get_test_app() + with app.flask_app.test_request_context(): + offset = url_for(controller='package', action='search') app.get(offset) # get redirected ... @@ -1372,7 +1540,8 @@ def test_search_page_request(self): factories.Dataset(name="dataset-two", title='Dataset Two') factories.Dataset(name="dataset-three", title='Dataset Three') - search_url = url_for(controller='package', action='search') + with app.flask_app.test_request_context(): + search_url = url_for(controller='package', action='search') search_response = app.get(search_url) assert_true('3 datasets found' in search_response) @@ -1395,7 +1564,8 @@ def test_search_page_results(self): factories.Dataset(name="dataset-two", title='Dataset Two') factories.Dataset(name="dataset-three", title='Dataset Three') - search_url = url_for(controller='package', action='search') + with app.flask_app.test_request_context(): + search_url = url_for(controller='package', action='search') search_response = app.get(search_url) search_form = search_response.forms['dataset-search-form'] @@ -1420,7 +1590,8 @@ def test_search_page_no_results(self): factories.Dataset(name="dataset-two", title='Dataset Two') factories.Dataset(name="dataset-three", title='Dataset Three') - search_url = url_for(controller='package', action='search') + with app.flask_app.test_request_context(): + search_url = url_for(controller='package', action='search') search_response = app.get(search_url) search_form = search_response.forms['dataset-search-form'] @@ -1445,7 +1616,8 @@ def test_search_page_results_tag(self): factories.Dataset(name="dataset-two", title='Dataset Two') factories.Dataset(name="dataset-three", title='Dataset Three') - search_url = url_for(controller='package', action='search') + with app.flask_app.test_request_context(): + search_url = url_for(controller='package', action='search') search_response = app.get(search_url) assert_true('/dataset?tags=my-tag' in search_response) @@ -1473,7 +1645,8 @@ def test_search_page_results_private(self): factories.Dataset(name="dataset-two", title='Dataset Two') factories.Dataset(name="dataset-three", title='Dataset Three') - search_url = url_for(controller='package', action='search') + with app.flask_app.test_request_context(): + search_url = url_for(controller='package', action='search') search_response = app.get(search_url) search_response_html = BeautifulSoup(search_response.body) @@ -1496,7 +1669,9 @@ def test_user_not_in_organization_cannot_search_private_datasets(self): private=True, ) env = {'REMOTE_USER': user['name'].encode('ascii')} - search_url = url_for(controller='package', action='search') + + with app.flask_app.test_request_context(): + search_url = url_for(controller='package', action='search') search_response = app.get(search_url, extra_environ=env) search_response_html = BeautifulSoup(search_response.body) @@ -1516,7 +1691,9 @@ def test_user_in_organization_can_search_private_datasets(self): private=True, ) env = {'REMOTE_USER': user['name'].encode('ascii')} - search_url = url_for(controller='package', action='search') + + with app.flask_app.test_request_context(): + search_url = url_for(controller='package', action='search') search_response = app.get(search_url, extra_environ=env) search_response_html = BeautifulSoup(search_response.body) @@ -1537,7 +1714,9 @@ def test_user_in_different_organization_cannot_search_private_datasets(self): private=True, ) env = {'REMOTE_USER': user['name'].encode('ascii')} - search_url = url_for(controller='package', action='search') + + with app.flask_app.test_request_context(): + search_url = url_for(controller='package', action='search') search_response = app.get(search_url, extra_environ=env) search_response_html = BeautifulSoup(search_response.body) @@ -1557,7 +1736,9 @@ def test_search_default_include_private_false(self): private=True, ) env = {'REMOTE_USER': user['name'].encode('ascii')} - search_url = url_for(controller='package', action='search') + + with app.flask_app.test_request_context(): + search_url = url_for(controller='package', action='search') search_response = app.get(search_url, extra_environ=env) search_response_html = BeautifulSoup(search_response.body) @@ -1576,7 +1757,9 @@ def test_sysadmin_can_search_private_datasets(self): private=True, ) env = {'REMOTE_USER': user['name'].encode('ascii')} - search_url = url_for(controller='package', action='search') + + with app.flask_app.test_request_context(): + search_url = url_for(controller='package', action='search') search_response = app.get(search_url, extra_environ=env) search_response_html = BeautifulSoup(search_response.body) @@ -1595,9 +1778,11 @@ def test_package_follow(self): package = factories.Dataset() env = {'REMOTE_USER': user['name'].encode('ascii')} - follow_url = url_for(controller='package', - action='follow', - id=package['id']) + + with app.flask_app.test_request_context(): + follow_url = url_for(controller='package', + action='follow', + id=package['id']) response = app.post(follow_url, extra_environ=env, status=302) response = response.follow() assert_true('You are now following {0}' @@ -1611,9 +1796,11 @@ def test_package_follow_not_exist(self): user_one = factories.User() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - follow_url = url_for(controller='package', - action='follow', - id='not-here') + + with app.flask_app.test_request_context(): + follow_url = url_for(controller='package', + action='follow', + id='not-here') response = app.post(follow_url, extra_environ=env, status=302) response = response.follow(status=404) assert_true('Dataset not found' in response) @@ -1625,13 +1812,16 @@ def test_package_unfollow(self): package = factories.Dataset() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - follow_url = url_for(controller='package', - action='follow', - id=package['id']) + + with app.flask_app.test_request_context(): + follow_url = url_for(controller='package', + action='follow', + id=package['id']) app.post(follow_url, extra_environ=env, status=302) - unfollow_url = url_for(controller='package', action='unfollow', - id=package['id']) + with app.flask_app.test_request_context(): + unfollow_url = url_for(controller='package', action='unfollow', + id=package['id']) unfollow_response = app.post(unfollow_url, extra_environ=env, status=302) unfollow_response = unfollow_response.follow() @@ -1648,8 +1838,10 @@ def test_package_unfollow_not_following(self): package = factories.Dataset() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - unfollow_url = url_for(controller='package', action='unfollow', - id=package['id']) + + with app.flask_app.test_request_context(): + unfollow_url = url_for(controller='package', action='unfollow', + id=package['id']) unfollow_response = app.post(unfollow_url, extra_environ=env, status=302) unfollow_response = unfollow_response.follow() @@ -1664,8 +1856,10 @@ def test_package_unfollow_not_exist(self): user_one = factories.User() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - unfollow_url = url_for(controller='package', action='unfollow', - id='not-here') + + with app.flask_app.test_request_context(): + unfollow_url = url_for(controller='package', action='unfollow', + id='not-here') unfollow_response = app.post(unfollow_url, extra_environ=env, status=302) unfollow_response = unfollow_response.follow(status=404) @@ -1679,13 +1873,16 @@ def test_package_follower_list(self): package = factories.Dataset() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - follow_url = url_for(controller='package', - action='follow', - id=package['id']) - app.post(follow_url, extra_environ=env, status=302) - followers_url = url_for(controller='package', action='followers', - id=package['id']) + with app.flask_app.test_request_context(): + follow_url = url_for(controller='package', + action='follow', + id=package['id']) + + followers_url = url_for(controller='package', action='followers', + id=package['id']) + + app.post(follow_url, extra_environ=env, status=302) # Only sysadmins can view the followers list pages followers_response = app.get(followers_url, extra_environ=env, @@ -1700,8 +1897,9 @@ def test_dataset_read(self): dataset = factories.Dataset() - url = url_for(controller='package', - action='read', - id=dataset['id']) + with app.flask_app.test_request_context(): + url = url_for(controller='package', + action='read', + id=dataset['id']) response = app.get(url) assert_in(dataset['title'], response) diff --git a/ckan/tests/controllers/test_tags.py b/ckan/tests/controllers/test_tags.py index 46b4b255b6f..3c34445e911 100644 --- a/ckan/tests/controllers/test_tags.py +++ b/ckan/tests/controllers/test_tags.py @@ -6,7 +6,7 @@ from nose.tools import assert_equal, assert_true, assert_false, assert_in from bs4 import BeautifulSoup -from routes import url_for +from ckan.lib.helpers import url_for import ckan.tests.helpers as helpers from ckan.tests import factories @@ -32,7 +32,8 @@ def test_tags_listed_under_50(self): expected_tags = _make_tag_list(49) factories.Dataset(tags=expected_tags) - tag_index_url = url_for(controller='tag', action='index') + with app.flask_app.test_request_context(): + tag_index_url = url_for(controller='tag', action='index') tag_response = app.get(tag_index_url) tag_response_html = BeautifulSoup(tag_response.body) @@ -53,7 +54,8 @@ def test_tags_listed_over_50(self): expected_tags = _make_tag_list(51) factories.Dataset(tags=expected_tags) - tag_index_url = url_for(controller='tag', action='index') + with app.flask_app.test_request_context(): + tag_index_url = url_for(controller='tag', action='index') tag_response = app.get(tag_index_url) tag_response_html = BeautifulSoup(tag_response.body) @@ -76,7 +78,8 @@ def test_tag_search(self): expected_tags.append({'name': 'find-me'}) factories.Dataset(tags=expected_tags) - tag_index_url = url_for(controller='tag', action='index') + with app.flask_app.test_request_context(): + tag_index_url = url_for(controller='tag', action='index') tag_response = app.get(tag_index_url) search_form = tag_response.forms[1] @@ -98,7 +101,8 @@ def test_tag_search_no_results(self): expected_tags = _make_tag_list(50) factories.Dataset(tags=expected_tags) - tag_index_url = url_for(controller='tag', action='index') + with app.flask_app.test_request_context(): + tag_index_url = url_for(controller='tag', action='index') tag_response = app.get(tag_index_url) search_form = tag_response.forms[1] @@ -121,7 +125,8 @@ def test_tag_read_redirects_to_dataset_search(self): app = self._get_test_app() factories.Dataset(title='My Other Dataset', tags=[{'name': 'find-me'}]) - tag_url = url_for(controller='tag', action='read', id='find-me') + with app.flask_app.test_request_context(): + tag_url = url_for(controller='tag', action='read', id='find-me') tag_response = app.get(tag_url, status=302) assert_equal(tag_response.headers['Location'], 'http://test.ckan.net/dataset?tags=find-me') @@ -131,5 +136,6 @@ def test_tag_read_not_found(self): app = self._get_test_app() factories.Dataset(title='My Other Dataset', tags=[{'name': 'find-me'}]) - tag_url = url_for(controller='tag', action='read', id='not-here') + with app.flask_app.test_request_context(): + tag_url = url_for(controller='tag', action='read', id='not-here') app.get(tag_url, status=404) diff --git a/ckan/tests/controllers/test_user.py b/ckan/tests/controllers/test_user.py index b3f63d12bc7..045ebf5d8d5 100644 --- a/ckan/tests/controllers/test_user.py +++ b/ckan/tests/controllers/test_user.py @@ -3,7 +3,7 @@ from bs4 import BeautifulSoup from nose.tools import assert_true, assert_false, assert_equal -from routes import url_for +from ckan.lib.helpers import url_for import ckan.tests.helpers as helpers import ckan.tests.factories as factories @@ -18,8 +18,11 @@ def _get_user_edit_page(app): user = factories.User() env = {'REMOTE_USER': user['name'].encode('ascii')} + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='edit') + response = app.get( - url=url_for(controller='user', action='edit'), + url=url, extra_environ=env, ) return env, response, user @@ -28,7 +31,11 @@ def _get_user_edit_page(app): class TestRegisterUser(helpers.FunctionalTestBase): def test_register_a_user(self): app = helpers._get_test_app() - response = app.get(url=url_for(controller='user', action='register')) + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='register') + + response = app.get(url) form = response.forms['user-register-form'] form['name'] = 'newuser' @@ -47,7 +54,11 @@ def test_register_a_user(self): def test_register_user_bad_password(self): app = helpers._get_test_app() - response = app.get(url=url_for(controller='user', action='register')) + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='register') + + response = app.get(url) form = response.forms['user-register-form'] form['name'] = 'newuser' @@ -77,9 +88,10 @@ def test_create_user_as_sysadmin(self): # submit it login_form.submit('save') - response = app.get( - url=url_for(controller='user', action='register'), - ) + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='register') + response = app.get(url) + assert "user-register-form" in response.forms form = response.forms['user-register-form'] form['name'] = 'newestuser' @@ -166,7 +178,8 @@ def test_user_logout_url_redirect(self): ''' app = self._get_test_app() - logout_url = url_for(controller='user', action='logout') + with app.flask_app.test_request_context(): + logout_url = url_for(controller='user', action='logout') logout_response = app.get(logout_url, status=302) final_response = helpers.webtest_maybe_follow(logout_response) @@ -183,7 +196,10 @@ def test_non_root_user_logout_url_redirect(self): ''' app = self._get_test_app() - logout_url = url_for(controller='user', action='logout') + with app.flask_app.test_request_context(): + logout_url = url_for(controller='user', action='logout') + # Remove the prefix otherwise the test app won't find the correct route + logout_url = logout_url.replace('/my/prefix', '') logout_response = app.get(logout_url, status=302) assert_equal(logout_response.status_int, 302) assert_true('/my/prefix/user/logout' in logout_response.location) @@ -200,8 +216,12 @@ def test_own_datasets_show_up_on_user_dashboard(self): app = self._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='dashboard_datasets') + response = app.get( - url=url_for(controller='user', action='dashboard_datasets'), + url, extra_environ=env, ) @@ -217,8 +237,12 @@ def test_other_datasets_dont_show_up_on_user_dashboard(self): app = self._get_test_app() env = {'REMOTE_USER': user2['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='dashboard_datasets') + response = app.get( - url=url_for(controller='user', action='dashboard_datasets'), + url, extra_environ=env, ) @@ -229,8 +253,12 @@ class TestUserEdit(helpers.FunctionalTestBase): def test_user_edit_no_user(self): app = self._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='edit', id=None) + response = app.get( - url_for(controller='user', action='edit', id=None), + url, status=400 ) assert_true('No user specified' in response) @@ -239,8 +267,12 @@ def test_user_edit_unknown_user(self): '''Attempt to read edit user for an unknown user redirects to login page.''' app = self._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='edit', id='unknown_person') + response = app.get( - url_for(controller='user', action='edit', id='unknown_person'), + url, status=403 ) @@ -250,8 +282,12 @@ def test_user_edit_not_logged_in(self): app = self._get_test_app() user = factories.User() username = user['name'] + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='edit', id=username) + response = app.get( - url_for(controller='user', action='edit', id=username), + url, status=403 ) @@ -259,8 +295,12 @@ def test_edit_user(self): user = factories.User(password='pass') app = self._get_test_app() env = {'REMOTE_USER': user['name'].encode('ascii')} + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='edit') + response = app.get( - url=url_for(controller='user', action='edit'), + url, extra_environ=env, ) # existing values in the form @@ -340,8 +380,12 @@ def test_edit_user_logged_in_username_change(self): login_form.submit() # Now the cookie is set, run the test + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='edit') + response = app.get( - url=url_for(controller='user', action='edit'), + url, ) # existing values in the form form = response.forms['user-edit-form'] @@ -351,7 +395,8 @@ def test_edit_user_logged_in_username_change(self): response = submit_and_follow(app, form, name='save') response = helpers.webtest_maybe_follow(response) - expected_url = url_for(controller='user', action='read', id='new-name') + with app.flask_app.test_request_context(): + expected_url = url_for(controller='user', action='read', id='new-name') assert response.request.path == expected_url def test_edit_user_logged_in_username_change_by_name(self): @@ -371,8 +416,12 @@ def test_edit_user_logged_in_username_change_by_name(self): login_form.submit() # Now the cookie is set, run the test + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='edit', id=user['name']) + response = app.get( - url=url_for(controller='user', action='edit', id=user['name']), + url, ) # existing values in the form form = response.forms['user-edit-form'] @@ -382,7 +431,8 @@ def test_edit_user_logged_in_username_change_by_name(self): response = submit_and_follow(app, form, name='save') response = helpers.webtest_maybe_follow(response) - expected_url = url_for(controller='user', action='read', id='new-name') + with app.flask_app.test_request_context(): + expected_url = url_for(controller='user', action='read', id='new-name') assert response.request.path == expected_url def test_edit_user_logged_in_username_change_by_id(self): @@ -402,8 +452,12 @@ def test_edit_user_logged_in_username_change_by_id(self): login_form.submit() # Now the cookie is set, run the test + + with app.flask_app.test_request_context(): + url = url_for(controller='user', action='edit', id=user['id']) + response = app.get( - url=url_for(controller='user', action='edit', id=user['id']), + url, ) # existing values in the form form = response.forms['user-edit-form'] @@ -413,7 +467,8 @@ def test_edit_user_logged_in_username_change_by_id(self): response = submit_and_follow(app, form, name='save') response = helpers.webtest_maybe_follow(response) - expected_url = url_for(controller='user', action='read', id='new-name') + with app.flask_app.test_request_context(): + expected_url = url_for(controller='user', action='read', id='new-name') assert response.request.path == expected_url def test_perform_reset_for_key_change(self): @@ -425,10 +480,12 @@ def test_perform_reset_for_key_change(self): key = user_obj.reset_key app = self._get_test_app() - offset = url_for(controller='user', - action='perform_reset', - id=user_obj.id, - key=user_obj.reset_key) + + with app.flask_app.test_request_context(): + offset = url_for(controller='user', + action='perform_reset', + id=user_obj.id, + key=user_obj.reset_key) response = app.post(offset, params=params, status=302) user_obj = helpers.model.User.by_name(user['name']) # Update user_obj @@ -479,9 +536,10 @@ def test_user_follow(self): user_two = factories.User() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - follow_url = url_for(controller='user', - action='follow', - id=user_two['id']) + with app.flask_app.test_request_context(): + follow_url = url_for(controller='user', + action='follow', + id=user_two['id']) response = app.post(follow_url, extra_environ=env, status=302) response = response.follow() assert_true('You are now following {0}' @@ -495,9 +553,10 @@ def test_user_follow_not_exist(self): user_one = factories.User() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - follow_url = url_for(controller='user', - action='follow', - id='not-here') + with app.flask_app.test_request_context(): + follow_url = url_for(controller='user', + action='follow', + id='not-here') response = app.post(follow_url, extra_environ=env, status=302) response = response.follow(status=404) assert_true('User not found' in response) @@ -509,13 +568,15 @@ def test_user_unfollow(self): user_two = factories.User() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - follow_url = url_for(controller='user', - action='follow', - id=user_two['id']) + with app.flask_app.test_request_context(): + follow_url = url_for(controller='user', + action='follow', + id=user_two['id']) app.post(follow_url, extra_environ=env, status=302) - unfollow_url = url_for(controller='user', action='unfollow', - id=user_two['id']) + with app.flask_app.test_request_context(): + unfollow_url = url_for(controller='user', action='unfollow', + id=user_two['id']) unfollow_response = app.post(unfollow_url, extra_environ=env, status=302) unfollow_response = unfollow_response.follow() @@ -532,8 +593,9 @@ def test_user_unfollow_not_following(self): user_two = factories.User() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - unfollow_url = url_for(controller='user', action='unfollow', - id=user_two['id']) + with app.flask_app.test_request_context(): + unfollow_url = url_for(controller='user', action='unfollow', + id=user_two['id']) unfollow_response = app.post(unfollow_url, extra_environ=env, status=302) unfollow_response = unfollow_response.follow() @@ -548,8 +610,9 @@ def test_user_unfollow_not_exist(self): user_one = factories.User() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - unfollow_url = url_for(controller='user', action='unfollow', - id='not-here') + with app.flask_app.test_request_context(): + unfollow_url = url_for(controller='user', action='unfollow', + id='not-here') unfollow_response = app.post(unfollow_url, extra_environ=env, status=302) unfollow_response = unfollow_response.follow(status=404) @@ -564,13 +627,15 @@ def test_user_follower_list(self): user_two = factories.User() env = {'REMOTE_USER': user_one['name'].encode('ascii')} - follow_url = url_for(controller='user', - action='follow', - id=user_two['id']) + with app.flask_app.test_request_context(): + follow_url = url_for(controller='user', + action='follow', + id=user_two['id']) app.post(follow_url, extra_environ=env, status=302) - followers_url = url_for(controller='user', action='followers', - id=user_two['id']) + with app.flask_app.test_request_context(): + followers_url = url_for(controller='user', action='followers', + id=user_two['id']) # Only sysadmins can view the followers list pages followers_response = app.get(followers_url, extra_environ=env, @@ -584,7 +649,8 @@ def test_user_page_anon_access(self): '''Anon users can access the user list page''' app = self._get_test_app() - user_url = url_for(controller='user', action='index') + with app.flask_app.test_request_context(): + user_url = url_for(controller='user', action='index') user_response = app.get(user_url, status=200) assert_true('All Users - CKAN' in user_response) @@ -596,7 +662,8 @@ def test_user_page_lists_users(self): factories.User(fullname='User Two') factories.User(fullname='User Three') - user_url = url_for(controller='user', action='index') + with app.flask_app.test_request_context(): + user_url = url_for(controller='user', action='index') user_response = app.get(user_url, status=200) user_response_html = BeautifulSoup(user_response.body) @@ -615,7 +682,8 @@ def test_user_page_doesnot_list_deleted_users(self): factories.User(fullname='User Two') factories.User(fullname='User Three') - user_url = url_for(controller='user', action='index') + with app.flask_app.test_request_context(): + user_url = url_for(controller='user', action='index') user_response = app.get(user_url, status=200) user_response_html = BeautifulSoup(user_response.body) @@ -634,7 +702,8 @@ def test_user_page_anon_search(self): factories.User(fullname='Person Two') factories.User(fullname='Person Three') - user_url = url_for(controller='user', action='index') + with app.flask_app.test_request_context(): + user_url = url_for(controller='user', action='index') user_response = app.get(user_url, status=200) search_form = user_response.forms['user-search-form'] search_form['q'] = 'Person' @@ -656,7 +725,8 @@ def test_user_page_anon_search_not_by_email(self): factories.User(fullname='Person Two') factories.User(fullname='Person Three') - user_url = url_for(controller='user', action='index') + with app.flask_app.test_request_context(): + user_url = url_for(controller='user', action='index') user_response = app.get(user_url, status=200) search_form = user_response.forms['user-search-form'] search_form['q'] = 'useroneemail@example.com' @@ -676,7 +746,8 @@ def test_user_page_sysadmin_user(self): factories.User(fullname='Person Three') env = {'REMOTE_USER': sysadmin['name'].encode('ascii')} - user_url = url_for(controller='user', action='index') + with app.flask_app.test_request_context(): + user_url = url_for(controller='user', action='index') user_response = app.get(user_url, status=200, extra_environ=env) search_form = user_response.forms['user-search-form'] search_form['q'] = 'useroneemail@example.com' diff --git a/ckan/tests/controllers/test_util.py b/ckan/tests/controllers/test_util.py index db76196e677..45616b60d67 100644 --- a/ckan/tests/controllers/test_util.py +++ b/ckan/tests/controllers/test_util.py @@ -1,10 +1,8 @@ # encoding: utf-8 from nose.tools import assert_equal -from pylons.test import pylonsapp -import paste.fixture -from routes import url_for as url_for +from ckan.lib.helpers import url_for import ckan.tests.helpers as helpers @@ -12,8 +10,12 @@ class TestUtil(helpers.FunctionalTestBase): def test_redirect_ok(self): app = self._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='util', action='redirect') + response = app.get( - url=url_for(controller='util', action='redirect'), + url, params={'url': '/dataset'}, status=302, ) @@ -22,24 +24,36 @@ def test_redirect_ok(self): def test_redirect_external(self): app = self._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='util', action='redirect') + response = app.get( - url=url_for(controller='util', action='redirect'), + url, params={'url': 'http://nastysite.com'}, status=403, ) def test_redirect_no_params(self): app = self._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='util', action='redirect') + response = app.get( - url=url_for(controller='util', action='redirect'), + url, params={}, status=400, ) def test_redirect_no_params_2(self): app = self._get_test_app() + + with app.flask_app.test_request_context(): + url = url_for(controller='util', action='redirect') + response = app.get( - url=url_for(controller='util', action='redirect'), + url, params={'url': ''}, status=400, ) diff --git a/ckan/tests/lib/test_helpers.py b/ckan/tests/lib/test_helpers.py index 0b67f25c353..9b1ae39e3e4 100644 --- a/ckan/tests/lib/test_helpers.py +++ b/ckan/tests/lib/test_helpers.py @@ -204,7 +204,6 @@ def test_url_for_qualified_with_root_path_locale_and_script_name_env(self): eq_(generated_url, url) - class TestHelpersUrlForFlaskandPylons2(BaseUrlFor): def test_url_for_flask_route_new_syntax(self): diff --git a/ckan/tests/lib/test_mailer.py b/ckan/tests/lib/test_mailer.py index 2ea839371cb..8f467e7bf72 100644 --- a/ckan/tests/lib/test_mailer.py +++ b/ckan/tests/lib/test_mailer.py @@ -37,6 +37,9 @@ def setup_class(cls): model.Session.commit() SmtpServerHarness.setup_class() + # Used to provide a context for url_for + cls.app = helpers._get_test_app() + @classmethod def teardown_class(cls): SmtpServerHarness.teardown_class() @@ -45,6 +48,13 @@ def teardown_class(cls): def setup(self): self.clear_smtp_messages() + self.request_context = self.app.flask_app.test_request_context() + self.request_context.push() + + def teardown(self): + + self.request_context.pop() + def mime_encode(self, msg, recipient_name): text = MIMEText(msg.encode('utf-8'), 'plain', 'utf-8') encoded_body = text.get_payload().strip() @@ -154,7 +164,9 @@ def test_send_reset_email(self): user = factories.User() user_obj = model.User.by_name(user['name']) - mailer.send_reset_link(user_obj) + # We need to provide a context as url_for is used internally + with self.app.flask_app.test_request_context(): + mailer.send_reset_link(user_obj) # check it went to the mock smtp server msgs = self.get_smtp_messages() @@ -163,7 +175,9 @@ def test_send_reset_email(self): assert_equal(msg[1], config['smtp.mail_from']) assert_equal(msg[2], [user['email']]) assert 'Reset' in msg[3], msg[3] - test_msg = mailer.get_reset_link_body(user_obj) + # We need to provide a context as url_for is used internally + with self.app.flask_app.test_request_context(): + test_msg = mailer.get_reset_link_body(user_obj) expected_body = self.mime_encode(test_msg, user['name']) @@ -174,8 +188,12 @@ def test_send_invite_email(self): user_obj = model.User.by_name(user['name']) assert user_obj.reset_key is None, user_obj - # send email - mailer.send_invite(user_obj) + # We need to provide a context as url_for is used internally + with self.app.flask_app.test_request_context(): + # send email + mailer.send_invite(user_obj) + + test_msg = mailer.get_invite_body(user_obj) # check it went to the mock smtp server msgs = self.get_smtp_messages() @@ -183,7 +201,6 @@ def test_send_invite_email(self): msg = msgs[0] assert_equal(msg[1], config['smtp.mail_from']) assert_equal(msg[2], [user['email']]) - test_msg = mailer.get_invite_body(user_obj) expected_body = self.mime_encode(test_msg, user['name']) @@ -197,8 +214,10 @@ def test_send_invite_email_with_group(self): group = factories.Group() role = 'member' - # send email - mailer.send_invite(user_obj, group_dict=group, role=role) + # We need to provide a context as url_for is used internally + with self.app.flask_app.test_request_context(): + # send email + mailer.send_invite(user_obj, group_dict=group, role=role) # check it went to the mock smtp server msgs = self.get_smtp_messages() @@ -214,8 +233,10 @@ def test_send_invite_email_with_org(self): org = factories.Organization() role = 'admin' - # send email - mailer.send_invite(user_obj, group_dict=org, role=role) + # We need to provide a context as url_for is used internally + with self.app.flask_app.test_request_context(): + # send email + mailer.send_invite(user_obj, group_dict=org, role=role) # check it went to the mock smtp server msgs = self.get_smtp_messages() diff --git a/ckan/tests/logic/action/test_create.py b/ckan/tests/logic/action/test_create.py index 41bad556f69..5aad45d74fe 100644 --- a/ckan/tests/logic/action/test_create.py +++ b/ckan/tests/logic/action/test_create.py @@ -114,8 +114,10 @@ def test_smtp_error_returns_error_message(self): 'role': 'editor' } - assert_raises(logic.ValidationError, helpers.call_action, - 'user_invite', context, **params) + app = helpers._get_test_app() + with app.flask_app.test_request_context(): + assert_raises(logic.ValidationError, helpers.call_action, + 'user_invite', context, **params) # Check that the pending user was deleted user = model.Session.query(model.User).filter( From 2d83e0d1366a76c8f83fd316301b9976f38fab62 Mon Sep 17 00:00:00 2001 From: amercader Date: Thu, 1 Sep 2016 12:56:28 +0100 Subject: [PATCH 05/71] [#3196] Fix legacy tests dependant on url_for Wrapping calls to url_for (and functions that call it firther down the line) with the Flask test_request_context, update functional tests to use the helpers._get_test_app function rather than old paster ones. --- ckan/tests/controllers/test_package.py | 4 +- ckan/tests/legacy/__init__.py | 5 +- ckan/tests/legacy/functional/api/base.py | 2 +- .../functional/api/model/test_package.py | 23 ++-- .../api/model/test_relationships.py | 16 +-- .../functional/api/model/test_vocabulary.py | 6 +- .../legacy/functional/api/test_activity.py | 4 +- .../legacy/functional/api/test_dashboard.py | 4 +- .../api/test_email_notifications.py | 13 +-- .../legacy/functional/api/test_follow.py | 8 +- .../legacy/functional/api/test_resource.py | 4 +- ckan/tests/legacy/functional/api/test_user.py | 29 +++-- ckan/tests/legacy/functional/api/test_util.py | 62 ++++++++--- ckan/tests/legacy/functional/test_activity.py | 16 ++- ckan/tests/legacy/functional/test_admin.py | 3 +- ckan/tests/legacy/functional/test_group.py | 14 ++- ckan/tests/legacy/functional/test_package.py | 66 ++++++++--- .../legacy/functional/test_pagination.py | 47 ++++++-- .../functional/test_preview_interface.py | 32 +++--- ckan/tests/legacy/functional/test_revision.py | 12 +- ckan/tests/legacy/functional/test_tag.py | 25 ++++- ckan/tests/legacy/functional/test_tracking.py | 56 +++++++--- ckan/tests/legacy/functional/test_user.py | 49 ++++++--- ckan/tests/legacy/html_check.py | 10 +- .../legacy/lib/test_alphabet_pagination.py | 5 +- ckan/tests/legacy/logic/test_action.py | 23 ++-- ckan/tests/legacy/logic/test_auth.py | 7 +- ckan/tests/legacy/misc/test_format_text.py | 103 +++++++++++++----- ckan/tests/legacy/models/test_package.py | 9 +- ckan/tests/legacy/test_coding_standards.py | 2 +- 30 files changed, 457 insertions(+), 202 deletions(-) diff --git a/ckan/tests/controllers/test_package.py b/ckan/tests/controllers/test_package.py index 6489d7fe33f..ceaec0e16d0 100644 --- a/ckan/tests/controllers/test_package.py +++ b/ckan/tests/controllers/test_package.py @@ -734,7 +734,7 @@ def test_delete_on_non_existing_dataset(self): with app.flask_app.test_request_context(): url = url_for(controller='package', action='delete', - id='schrodingersdatset') + id='schrodingersdatset') response = app.post( url, @@ -1815,7 +1815,7 @@ def test_package_unfollow(self): with app.flask_app.test_request_context(): follow_url = url_for(controller='package', - action='follow', + action='follow', id=package['id']) app.post(follow_url, extra_environ=env, status=302) diff --git a/ckan/tests/legacy/__init__.py b/ckan/tests/legacy/__init__.py index 3a056855f95..a647c147899 100644 --- a/ckan/tests/legacy/__init__.py +++ b/ckan/tests/legacy/__init__.py @@ -35,6 +35,7 @@ import ckan.model as model from ckan import ckan_nose_plugin from ckan.common import json +from ckan.tests import helpers # evil hack as url_for is passed out url_for = h.url_for @@ -237,7 +238,8 @@ class WsgiAppCase(BaseCase): # Either that, or this file got imported somehow before the tests started # running, meaning the pylonsapp wasn't setup yet (which is done in # pylons.test.py:begin()) - app = paste.fixture.TestApp(wsgiapp) + #app = paste.fixture.TestApp(wsgiapp) + app = helpers._get_test_app() def config_abspath(file_path): @@ -415,6 +417,7 @@ def call_action_api(app, action, apikey=None, status=200, **kwargs): params = json.dumps(kwargs) response = app.post('/api/action/{0}'.format(action), params=params, extra_environ={'Authorization': str(apikey)}, status=status) + assert '/api/3/action/help_show?name={0}'.format(action) \ in response.json['help'] diff --git a/ckan/tests/legacy/functional/api/base.py b/ckan/tests/legacy/functional/api/base.py index fefedae0f65..1a11b53c196 100644 --- a/ckan/tests/legacy/functional/api/base.py +++ b/ckan/tests/legacy/functional/api/base.py @@ -190,7 +190,7 @@ def loads(self, chars): raise Exception, "Couldn't loads string '%s': %s" % (chars, inst) def assert_json_response(self, res, expected_in_body=None): - content_type = res.header_dict['Content-Type'] + content_type = res.headers['Content-Type'] assert 'application/json' in content_type, content_type res_json = self.loads(res.body) if expected_in_body: diff --git a/ckan/tests/legacy/functional/api/model/test_package.py b/ckan/tests/legacy/functional/api/model/test_package.py index 22472d7dac3..593f49d7612 100644 --- a/ckan/tests/legacy/functional/api/model/test_package.py +++ b/ckan/tests/legacy/functional/api/model/test_package.py @@ -13,6 +13,7 @@ from ckan.tests.legacy.functional.api.base import Api2TestCase as Version2TestCase import ckan.tests.legacy as tests +from ckan.tests import helpers # Todo: Remove this ckan.model stuff. import ckan.model as model @@ -65,7 +66,7 @@ def test_register_post_ok(self): assert_equal(pkg['extras'], self.package_fixture_data['extras']) # Check the value of the Location header. - location = res.header('Location') + location = res.headers['Location'] assert offset in location res = self.app.get(location, status=self.STATUS_200_OK) @@ -133,7 +134,7 @@ def test_register_post_with_group(self): package_fixture_data = self.package_fixture_data package_fixture_data['groups'] = groups data = self.dumps(package_fixture_data) - res = self.post_json(offset, data, status=self.STATUS_201_CREATED, + res = self.app.post(offset, data, status=self.STATUS_201_CREATED, extra_environ={'Authorization':str(user.apikey)}) # Check the database record. @@ -159,7 +160,7 @@ def test_register_post_with_group_not_authorized(self): package_fixture_data = self.package_fixture_data package_fixture_data['groups'] = groups data = self.dumps(package_fixture_data) - res = self.post_json(offset, data, status=self.STATUS_403_ACCESS_DENIED, + res = self.app.post(offset, data, status=self.STATUS_403_ACCESS_DENIED, extra_environ=self.extra_environ) del package_fixture_data['groups'] @@ -173,7 +174,7 @@ def test_register_post_with_group_not_found(self): package_fixture_data = self.package_fixture_data package_fixture_data['groups'] = groups data = self.dumps(package_fixture_data) - res = self.post_json(offset, data, status=self.STATUS_404_NOT_FOUND, + res = self.app.post(offset, data, status=self.STATUS_404_NOT_FOUND, extra_environ=self.extra_environ) del package_fixture_data['groups'] @@ -187,7 +188,7 @@ def test_register_post_with_group_sysadmin(self): package_fixture_data = self.package_fixture_data package_fixture_data['groups'] = groups data = self.dumps(package_fixture_data) - res = self.post_json(offset, data, status=self.STATUS_201_CREATED, + res = self.app.post(offset, data, status=self.STATUS_201_CREATED, extra_environ={'Authorization':str(user.apikey)}) # Check the database record. model.Session.remove() @@ -207,7 +208,7 @@ def test_register_post_json(self): assert not self.get_package_by_name(self.package_fixture_data['name']) offset = self.package_offset() data = self.dumps(self.package_fixture_data) - res = self.post_json(offset, data, status=self.STATUS_201_CREATED, + res = self.app.post(offset, data, status=self.STATUS_201_CREATED, extra_environ=self.admin_extra_environ) # Check the database record. model.Session.remove() @@ -219,7 +220,7 @@ def test_register_post_bad_content_type(self): assert not self.get_package_by_name(self.package_fixture_data['name']) offset = self.package_offset() data = self.dumps(self.package_fixture_data) - res = self.http_request(offset, data, + res = self.app.post(offset, data, content_type='something/unheard_of', status=[self.STATUS_400_BAD_REQUEST, self.STATUS_201_CREATED], @@ -262,7 +263,7 @@ def test_register_post_indexerror(self): offset = self.package_offset() data = self.dumps(self.package_fixture_data) - self.post_json(offset, data, status=500, extra_environ=self.admin_extra_environ) + self.app.post(offset, data, status=500, extra_environ=self.admin_extra_environ) model.Session.remove() finally: SolrSettings.init(original_settings) @@ -273,7 +274,7 @@ def test_register_post_tag_too_long(self): assert not self.get_package_by_name(pkg['name']) offset = self.package_offset() data = self.dumps(pkg) - res = self.post_json(offset, data, status=self.STATUS_409_CONFLICT, + res = self.app.post(offset, data, status=self.STATUS_409_CONFLICT, extra_environ=self.admin_extra_environ) assert 'length is more than maximum 100' in res.body, res.body assert 'tagok' not in res.body @@ -714,8 +715,8 @@ def test_entity_delete_ok_without_request_headers(self): assert self.get_package_by_name(self.package_fixture_data['name']) # delete it offset = self.package_offset(self.package_fixture_data['name']) - res = self.delete_request(offset, status=self.STATUS_200_OK, - extra_environ=self.admin_extra_environ) + res = self.app.delete(offset, status=self.STATUS_200_OK, + extra_environ=self.admin_extra_environ) package = self.get_package_by_name(self.package_fixture_data['name']) self.assert_equal(package.state, 'deleted') model.Session.remove() diff --git a/ckan/tests/legacy/functional/api/model/test_relationships.py b/ckan/tests/legacy/functional/api/model/test_relationships.py index 0bdc30c84e5..069776d663d 100644 --- a/ckan/tests/legacy/functional/api/model/test_relationships.py +++ b/ckan/tests/legacy/functional/api/model/test_relationships.py @@ -1,14 +1,14 @@ # encoding: utf-8 -from nose.tools import assert_equal +from nose.tools import assert_equal from nose.plugins.skip import SkipTest from ckan import model from ckan.lib.create_test_data import CreateTestData from ckan.tests.legacy.functional.api.base import BaseModelApiTestCase -from ckan.tests.legacy.functional.api.base import Api1TestCase as Version1TestCase -from ckan.tests.legacy.functional.api.base import Api2TestCase as Version2TestCase +from ckan.tests.legacy.functional.api.base import Api1TestCase as Version1TestCase +from ckan.tests.legacy.functional.api.base import Api2TestCase as Version2TestCase class RelationshipsTestCase(BaseModelApiTestCase): @@ -115,7 +115,7 @@ def test_01_create_and_read_relationship(self): assert len(rels) == 1 self.check_relationship_dict(rels[0], 'annakarenina', 'parent_of', 'warandpeace', self.comment) - + def test_02_create_relationship_way_2(self): # Create a relationship using 2nd way self.create_annakarenina_parent_of_war_and_peace(way=2) @@ -189,7 +189,7 @@ def test_create_relationship_unknown(self): def create_annakarenina_parent_of_war_and_peace(self, way=1): # Create package relationship. # More than one 'way' to create a package. - # Todo: Redesign this in a RESTful style, so that a relationship is + # Todo: Redesign this in a RESTful style, so that a relationship is # created by posting a relationship to a relationship **register**. assert way in (1, 2, 3, 4) if way == 1: @@ -220,7 +220,7 @@ def create_annakarenina_parent_of_war_and_peace(self, way=1): assert_equal(rel['type'], 'child_of') assert_equal(rel['subject'], self.ref_package(self.war)) assert_equal(rel['object'], self.ref_package(self.anna)) - + # Check the model, directly. rels = self.anna.get_relationships() assert len(rels) == 1, rels @@ -271,7 +271,7 @@ def get_relationships(self, package1_name=u'annakarenina', type='relationships', if type: allowable_statuses.append(404) res = self.app.get(offset, status=allowable_statuses) - if res.status == 200: + if res.status_int == 200: res_dict = self.data_from_res(res) if res.body else [] return res_dict else: @@ -300,7 +300,7 @@ def check_relationships_rest(self, pkg1_name, pkg2_name=None, expected_relationships=[]): rels = self.get_relationships(package1_name=pkg1_name, package2_name=pkg2_name) - self.assert_len_relationships(rels, expected_relationships) + self.assert_len_relationships(rels, expected_relationships) for rel in rels: the_expected_rel = None for expected_rel in expected_relationships: diff --git a/ckan/tests/legacy/functional/api/model/test_vocabulary.py b/ckan/tests/legacy/functional/api/model/test_vocabulary.py index feb03af3717..ab6bb25f6f2 100644 --- a/ckan/tests/legacy/functional/api/model/test_vocabulary.py +++ b/ckan/tests/legacy/functional/api/model/test_vocabulary.py @@ -1,17 +1,17 @@ # encoding: utf-8 import ckan -import pylons.test -import paste.fixture import ckan.lib.helpers as helpers import ckan.lib.dictization.model_dictize as model_dictize +from ckan.tests import helpers as test_helpers + class TestVocabulary(object): @classmethod def setup_class(self): - self.app = paste.fixture.TestApp(pylons.test.pylonsapp) + self.app = test_helpers._get_test_app() @classmethod def teardown_class(self): diff --git a/ckan/tests/legacy/functional/api/test_activity.py b/ckan/tests/legacy/functional/api/test_activity.py index 1350b7acaba..114d91b6723 100644 --- a/ckan/tests/legacy/functional/api/test_activity.py +++ b/ckan/tests/legacy/functional/api/test_activity.py @@ -22,6 +22,8 @@ from ckan.common import json import ckan.tests.legacy as tests +from ckan.tests import helpers + ##def package_update(context, data_dict): ## # These tests call package_update directly which is really bad @@ -204,7 +206,7 @@ def setup_class(self): 'id': annakarenina.id, } self.users = [self.sysadmin_user, self.normal_user] - self.app = paste.fixture.TestApp(pylons.test.pylonsapp) + self.app = helpers._get_test_app() @classmethod def teardown_class(self): diff --git a/ckan/tests/legacy/functional/api/test_dashboard.py b/ckan/tests/legacy/functional/api/test_dashboard.py index 7482dd1a839..7b7364aa57d 100644 --- a/ckan/tests/legacy/functional/api/test_dashboard.py +++ b/ckan/tests/legacy/functional/api/test_dashboard.py @@ -12,6 +12,8 @@ import paste import pylons.test from ckan.tests.legacy import CreateTestData +from ckan.tests import helpers + class TestDashboard(object): '''Tests for the logic action functions related to the user's dashboard.''' @@ -34,7 +36,7 @@ def user_create(cls): def setup_class(cls): ckan.lib.search.clear_all() CreateTestData.create() - cls.app = paste.fixture.TestApp(pylons.test.pylonsapp) + cls.app = helpers._get_test_app() joeadmin = ckan.model.User.get('joeadmin') cls.joeadmin = { 'id': joeadmin.id, diff --git a/ckan/tests/legacy/functional/api/test_email_notifications.py b/ckan/tests/legacy/functional/api/test_email_notifications.py index 35bea72dbcb..f8505201836 100644 --- a/ckan/tests/legacy/functional/api/test_email_notifications.py +++ b/ckan/tests/legacy/functional/api/test_email_notifications.py @@ -10,13 +10,12 @@ import ckan.tests.legacy.pylons_controller as pylons_controller import ckan.config.middleware -import paste -import paste.deploy -import pylons.test +from ckan.tests import helpers from ckan.common import config + class TestEmailNotifications(mock_mail_server.SmtpServerHarness, pylons_controller.PylonsTestCase): @@ -25,7 +24,7 @@ def setup_class(cls): mock_mail_server.SmtpServerHarness.setup_class() pylons_controller.PylonsTestCase.setup_class() tests.CreateTestData.create() - cls.app = paste.fixture.TestApp(pylons.test.pylonsapp) + cls.app = helpers._get_test_app() joeadmin = model.User.get('joeadmin') cls.joeadmin = {'id': joeadmin.id, 'apikey': joeadmin.apikey, @@ -198,7 +197,7 @@ def setup_class(cls): mock_mail_server.SmtpServerHarness.setup_class() pylons_controller.PylonsTestCase.setup_class() tests.CreateTestData.create() - cls.app = paste.fixture.TestApp(pylons.test.pylonsapp) + cls.app = helpers._get_test_app() joeadmin = model.User.get('joeadmin') cls.joeadmin = {'id': joeadmin.id, 'apikey': joeadmin.apikey, @@ -338,7 +337,7 @@ def setup_class(cls): wsgiapp = ckan.config.middleware.make_app(config['global_conf'], **config) - cls.app = paste.fixture.TestApp(wsgiapp) + cls.app = helpers._get_test_app() mock_mail_server.SmtpServerHarness.setup_class() pylons_controller.PylonsTestCase.setup_class() @@ -422,7 +421,7 @@ def setup_class(cls): wsgiapp = ckan.config.middleware.make_app(config['global_conf'], **config) - cls.app = paste.fixture.TestApp(wsgiapp) + cls.app = helpers._get_test_app() mock_mail_server.SmtpServerHarness.setup_class() pylons_controller.PylonsTestCase.setup_class() diff --git a/ckan/tests/legacy/functional/api/test_follow.py b/ckan/tests/legacy/functional/api/test_follow.py index 909b2e77606..98f4bd23073 100644 --- a/ckan/tests/legacy/functional/api/test_follow.py +++ b/ckan/tests/legacy/functional/api/test_follow.py @@ -18,6 +18,8 @@ import ckan from ckan.tests.legacy import are_foreign_keys_supported, SkipTest, CreateTestData, call_action_api +from ckan.tests import helpers + def datetime_from_string(s): '''Return a standard datetime.datetime object initialised from a string in @@ -295,7 +297,7 @@ def setup_class(self): 'id': ckan.model.Group.get('david').id, 'name': ckan.model.Group.get('david').name, } - self.app = paste.fixture.TestApp(pylons.test.pylonsapp) + self.app = helpers._get_test_app() @classmethod def teardown_class(self): @@ -804,7 +806,7 @@ def setup_class(self): 'id': ckan.model.Group.get('david').id, 'name': ckan.model.Group.get('david').name, } - self.app = paste.fixture.TestApp(pylons.test.pylonsapp) + self.app = helpers._get_test_app() follow_user(self.app, self.testsysadmin['id'], self.testsysadmin['apikey'], self.joeadmin['id'], self.joeadmin['id'], self.testsysadmin['apikey']) @@ -1154,7 +1156,7 @@ def setup_class(self): 'id': ckan.model.Group.get('david').id, 'name': ckan.model.Group.get('david').name, } - self.app = paste.fixture.TestApp(pylons.test.pylonsapp) + self.app = helpers._get_test_app() follow_user(self.app, self.joeadmin['id'], self.joeadmin['apikey'], self.testsysadmin['id'], self.testsysadmin['id'], diff --git a/ckan/tests/legacy/functional/api/test_resource.py b/ckan/tests/legacy/functional/api/test_resource.py index e8c53593bcd..28c3a6bed15 100644 --- a/ckan/tests/legacy/functional/api/test_resource.py +++ b/ckan/tests/legacy/functional/api/test_resource.py @@ -45,7 +45,7 @@ def teardown_class(self): def test_good_input(self): offset = self.base_url + '/format_autocomplete?incomplete=cs' result = self.app.get(offset, status=200) - content_type = result.header_dict['Content-Type'] + content_type = result.headers['Content-Type'] assert 'application/json' in content_type, content_type res_json = self.loads(result.body) assert 'ResultSet' in res_json, res_json @@ -58,7 +58,7 @@ def test_good_input(self): def test_missing_format(self): offset = self.base_url + '/format_autocomplete?incomplete=incorrectformat' result = self.app.get(offset, status=200) - content_type = result.header_dict['Content-Type'] + content_type = result.headers['Content-Type'] assert 'application/json' in content_type, content_type res_json = self.loads(result.body) assert 'ResultSet' in res_json, res_json diff --git a/ckan/tests/legacy/functional/api/test_user.py b/ckan/tests/legacy/functional/api/test_user.py index e470ce2d8bd..b58daface79 100644 --- a/ckan/tests/legacy/functional/api/test_user.py +++ b/ckan/tests/legacy/functional/api/test_user.py @@ -13,6 +13,7 @@ from ckan.tests.legacy import url_for import ckan.config.middleware from ckan.common import json +from ckan.tests import helpers class TestUserApi(ControllerTestCase): @@ -25,8 +26,12 @@ def teardown_class(cls): model.repo.rebuild_db() def test_autocomplete(self): + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='user_autocomplete', ver=2) + response = self.app.get( - url=url_for(controller='api', action='user_autocomplete', ver=2), + url, params={ 'q': u'sysadmin', }, @@ -35,11 +40,15 @@ def test_autocomplete(self): print response.json assert set(response.json[0].keys()) == set(['id', 'name', 'fullname']) assert_equal(response.json[0]['name'], u'testsysadmin') - assert_equal(response.header('Content-Type'), 'application/json;charset=utf-8') + assert_equal(response.headers['Content-Type'], 'application/json;charset=utf-8') def test_autocomplete_multiple(self): + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='user_autocomplete', ver=2) + response = self.app.get( - url=url_for(controller='api', action='user_autocomplete', ver=2), + url, params={ 'q': u'tes', }, @@ -49,8 +58,12 @@ def test_autocomplete_multiple(self): assert_equal(len(response.json), 2) def test_autocomplete_limit(self): + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='user_autocomplete', ver=2) + response = self.app.get( - url=url_for(controller='api', action='user_autocomplete', ver=2), + url, params={ 'q': u'tes', 'limit': 1 @@ -72,7 +85,7 @@ def setup_class(cls): cls._original_config = config.copy() wsgiapp = ckan.config.middleware.make_app( config['global_conf'], **config) - cls.app = paste.fixture.TestApp(wsgiapp) + cls.app = helpers._get_test_app() cls.sysadmin_user = model.User.get('testsysadmin') PylonsTestCase.setup_class() @@ -122,7 +135,7 @@ def setup_class(cls): config['ckan.auth.create_user_via_api'] = True wsgiapp = ckan.config.middleware.make_app( config['global_conf'], **config) - cls.app = paste.fixture.TestApp(wsgiapp) + cls.app = helpers._get_test_app() PylonsTestCase.setup_class() cls.sysadmin_user = model.User.get('testsysadmin') @@ -170,7 +183,7 @@ def setup_class(cls): config['ckan.auth.create_user_via_web'] = False wsgiapp = ckan.config.middleware.make_app( config['global_conf'], **config) - cls.app = paste.fixture.TestApp(wsgiapp) + cls.app = helpers._get_test_app() cls.sysadmin_user = model.User.get('testsysadmin') PylonsTestCase.setup_class() @@ -206,7 +219,7 @@ def setup_class(cls): config['ckan.auth.create_user_via_web'] = True wsgiapp = ckan.config.middleware.make_app( config['global_conf'], **config) - cls.app = paste.fixture.TestApp(wsgiapp) + cls.app = helpers._get_test_app() cls.sysadmin_user = model.User.get('testsysadmin') PylonsTestCase.setup_class() diff --git a/ckan/tests/legacy/functional/api/test_util.py b/ckan/tests/legacy/functional/api/test_util.py index 9ba2adb9afe..9065d00e7da 100644 --- a/ckan/tests/legacy/functional/api/test_util.py +++ b/ckan/tests/legacy/functional/api/test_util.py @@ -18,8 +18,12 @@ def teardown_class(cls): model.repo.rebuild_db() def test_package_slug_invalid(self): + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='is_slug_valid', ver=2) + response = self.app.get( - url=url_for(controller='api', action='is_slug_valid', ver=2), + url, params={ 'type': u'package', 'slug': u'edit', @@ -27,10 +31,14 @@ def test_package_slug_invalid(self): status=200, ) assert_equal(response.body, '{"valid": false}') - assert_equal(response.header('Content-Type'), 'application/json;charset=utf-8') + assert_equal(response.headers['Content-Type'], 'application/json;charset=utf-8') + + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='is_slug_valid', ver=2) response = self.app.get( - url=url_for(controller='api', action='is_slug_valid', ver=2), + url, params={ 'type': u'package', 'slug': u'new', @@ -38,11 +46,15 @@ def test_package_slug_invalid(self): status=200, ) assert_equal(response.body, '{"valid": false}') - assert_equal(response.header('Content-Type'), 'application/json;charset=utf-8') + assert_equal(response.headers['Content-Type'], 'application/json;charset=utf-8') def test_package_slug_valid(self): + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='is_slug_valid', ver=2) + response = self.app.get( - url=url_for(controller='api', action='is_slug_valid', ver=2), + url, params={ 'type': u'package', 'slug': u'A New Title * With & Funny CHARacters', @@ -50,10 +62,14 @@ def test_package_slug_valid(self): status=200, ) assert_equal(response.body, '{"valid": true}') - assert_equal(response.header('Content-Type'), 'application/json;charset=utf-8') + assert_equal(response.headers['Content-Type'], 'application/json;charset=utf-8') + + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='is_slug_valid', ver=2) response = self.app.get( - url=url_for(controller='api', action='is_slug_valid', ver=2), + url, params={ 'type': u'package', 'slug': u'warandpeace', @@ -61,44 +77,64 @@ def test_package_slug_valid(self): status=200, ) assert_equal(response.body, '{"valid": false}') - assert_equal(response.header('Content-Type'), 'application/json;charset=utf-8') + assert_equal(response.headers['Content-Type'], 'application/json;charset=utf-8') def test_markdown(self): markdown = '''##Title''' + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='markdown', ver=2) + response = self.app.get( - url=url_for(controller='api', action='markdown', ver=2), + url, params={'q': markdown}, status=200, ) assert_equal(response.body, '"

Title

"') def test_munge_package_name(self): + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='munge_package_name', ver=2) + response = self.app.get( - url=url_for(controller='api', action='munge_package_name', ver=2), + url, params={'name': 'test name'}, status=200, ) assert_equal(response.body, '"test-name"') def test_munge_title_to_package_name(self): + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='munge_title_to_package_name', ver=2) + response = self.app.get( - url=url_for(controller='api', action='munge_title_to_package_name', ver=2), + url, params={'name': 'Test title'}, status=200, ) assert_equal(response.body, '"test-title"') def test_munge_tag(self): + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='munge_tag', ver=2) + response = self.app.get( - url=url_for(controller='api', action='munge_tag', ver=2), + url, params={'name': 'Test subject'}, status=200, ) assert_equal(response.body, '"test-subject"') def test_status(self): + + with self.app.flask_app.test_request_context(): + url = url_for(controller='api', action='status', ver=2) + response = self.app.get( - url=url_for(controller='api', action='status', ver=2), + url, params={}, status=200, ) diff --git a/ckan/tests/legacy/functional/test_activity.py b/ckan/tests/legacy/functional/test_activity.py index f40f1397d78..61eab03ea0d 100644 --- a/ckan/tests/legacy/functional/test_activity.py +++ b/ckan/tests/legacy/functional/test_activity.py @@ -4,7 +4,7 @@ from pylons.test import pylonsapp from paste.deploy.converters import asbool import paste.fixture -from routes import url_for +from ckan.lib.helpers import url_for from nose import SkipTest import ckan @@ -14,9 +14,10 @@ from ckan.logic.action.update import user_update, group_update from ckan.logic.action.delete import package_delete from ckan.tests.legacy.html_check import HtmlCheckMethods -from ckan.tests.legacy import CreateTestData +from ckan.tests.legacy import CreateTestData, WsgiAppCase -class TestActivity(HtmlCheckMethods): + +class TestActivity(WsgiAppCase, HtmlCheckMethods): """Test the rendering of activity streams into HTML pages. Activity streams are tested in detail elsewhere, this class just briefly @@ -29,7 +30,6 @@ def setup(cls): raise SkipTest('Activity streams not enabled') CreateTestData.create() cls.sysadmin_user = ckan.model.User.get('testsysadmin') - cls.app = paste.fixture.TestApp(pylonsapp) @classmethod def teardown(cls): @@ -52,7 +52,9 @@ def test_user_activity(self): 'allow_partial_update': True, } user = user_create(context, user_dict) - offset = url_for(controller='user', action='activity', id=user['id']) + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='user', action='activity', id=user['id']) result = self.app.get(offset, status=200) stripped = self.strip_tags(result) assert '%s signed up' % user['fullname'] in stripped, stripped @@ -239,7 +241,9 @@ def test_user_activity(self): # The user's dashboard page should load successfully and have the # latest 15 activities on it. - offset = url_for(controller='user', action='dashboard') + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='user', action='dashboard') extra_environ = {'Authorization': str(ckan.model.User.get('billybeane').apikey)} result = self.app.post(offset, extra_environ=extra_environ, diff --git a/ckan/tests/legacy/functional/test_admin.py b/ckan/tests/legacy/functional/test_admin.py index 7737f036650..41ba685fc38 100644 --- a/ckan/tests/legacy/functional/test_admin.py +++ b/ckan/tests/legacy/functional/test_admin.py @@ -15,7 +15,8 @@ def teardown_class(self): #test that only sysadmins can access the /ckan-admin page def test_index(self): - url = url_for('ckanadmin', action='index') + with self.app.flask_app.test_request_context(): + url = url_for('ckanadmin', action='index') response = self.app.get(url, status=[403]) # random username response = self.app.get(url, status=[403], diff --git a/ckan/tests/legacy/functional/test_group.py b/ckan/tests/legacy/functional/test_group.py index 0223375f232..1e952879ad1 100644 --- a/ckan/tests/legacy/functional/test_group.py +++ b/ckan/tests/legacy/functional/test_group.py @@ -95,7 +95,9 @@ def test_sorting(self): def test_read_non_existent(self): name = u'group_does_not_exist' - offset = url_for(controller='group', action='read', id=name) + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='group', action='read', id=name) res = self.app.get(offset, status=404) @@ -131,8 +133,10 @@ def teardown_class(self): model.repo.rebuild_db() def test_2_atom_feed(self): - offset = url_for(controller='group', action='history', - id=self.grp.name) + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='group', action='history', + id=self.grp.name) offset = "%s?format=atom" % offset res = self.app.get(offset) assert ']') # edit the package - self.offset = url_for(controller='package', action='edit', id=self.editpkg_name) + + with self.app.flask_app.test_request_context(): + self.offset = url_for(controller='package', action='edit', id=self.editpkg_name) self.res = self.app.get(self.offset, extra_environ=self.extra_environ_admin) fv = self.res.forms['dataset-edit'] fv['title'] = u'New Title' @@ -547,7 +564,8 @@ def test_delete(self): plugins.load('test_package_controller_plugin') plugin = plugins.get_plugin('test_package_controller_plugin') - offset = url_for(controller='package', action='delete', + with self.app.flask_app.test_request_context(): + offset = url_for(controller='package', action='delete', id='warandpeace') # Since organizations, any owned dataset can be edited/deleted by any # user @@ -582,7 +600,9 @@ def teardown_class(self): def test_new_plugin_hook(self): plugins.load('test_package_controller_plugin') plugin = plugins.get_plugin('test_package_controller_plugin') - offset = url_for(controller='package', action='new') + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='package', action='new') res = self.app.get(offset, extra_environ=self.extra_environ_tester) new_name = u'plugged' fv = res.forms['dataset-edit'] @@ -597,7 +617,9 @@ def test_new_plugin_hook(self): def test_after_create_plugin_hook(self): plugins.load('test_package_controller_plugin') plugin = plugins.get_plugin('test_package_controller_plugin') - offset = url_for(controller='package', action='new') + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='package', action='new') res = self.app.get(offset, extra_environ=self.extra_environ_tester) new_name = u'plugged2' fv = res.forms['dataset-edit'] @@ -617,8 +639,8 @@ def test_new_indexerror(self): try: SolrSettings.init(bad_solr_url) new_package_name = u'new-package-missing-solr' - - offset = url_for(controller='package', action='new') + with self.app.flask_app.test_request_context(): + offset = url_for(controller='package', action='new') res = self.app.get(offset, extra_environ=self.extra_environ_tester) fv = res.forms['dataset-edit'] fv['name'] = new_package_name @@ -633,7 +655,9 @@ def test_new_indexerror(self): SolrSettings.init(solr_url) def test_change_locale(self): - offset = url_for(controller='package', action='new') + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='package', action='new') res = self.app.get(offset, extra_environ=self.extra_environ_tester) res = self.app.get('/de/dataset/new', extra_environ=self.extra_environ_tester) @@ -683,12 +707,16 @@ def teardown_class(self): model.repo.rebuild_db() def test_read(self): - offset = url_for(controller='package', action='read', id=self.non_active_name) + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='package', action='read', id=self.non_active_name) res = self.app.get(offset, status=[404]) def test_read_as_admin(self): - offset = url_for(controller='package', action='read', id=self.non_active_name) + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='package', action='read', id=self.non_active_name) res = self.app.get(offset, status=200, extra_environ={'REMOTE_USER':'testsysadmin'}) @@ -718,7 +746,9 @@ def setup_class(cls): cls.revision_ids = [rev[0].id for rev in cls.pkg1.all_related_revisions] # revision ids are newest first cls.revision_timestamps = [rev[0].timestamp for rev in cls.pkg1.all_related_revisions] - cls.offset = url_for(controller='package', action='history', id=cls.pkg1.name) + + with cls.app.flask_app.test_request_context(): + cls.offset = url_for(controller='package', action='history', id=cls.pkg1.name) @classmethod def teardown_class(cls): diff --git a/ckan/tests/legacy/functional/test_pagination.py b/ckan/tests/legacy/functional/test_pagination.py index 596bc5fa453..3a4fc7912c7 100644 --- a/ckan/tests/legacy/functional/test_pagination.py +++ b/ckan/tests/legacy/functional/test_pagination.py @@ -59,25 +59,41 @@ def teardown_class(self): model.repo.rebuild_db() def test_package_search_p1(self): - res = self.app.get(url_for(controller='package', action='search', q='groups:group_00')) + + with self.app.flask_app.test_request_context(): + url = url_for(controller='package', action='search', q='groups:group_00') + + res = self.app.get(url) assert 'href="/dataset?q=groups%3Agroup_00&page=2"' in res pkg_numbers = scrape_search_results(res, 'dataset') assert_equal(['50', '49', '48', '47', '46', '45', '44', '43', '42', '41', '40', '39', '38', '37', '36', '35', '34', '33', '32', '31'], pkg_numbers) def test_package_search_p2(self): - res = self.app.get(url_for(controller='package', action='search', q='groups:group_00', page=2)) + + with self.app.flask_app.test_request_context(): + url = url_for(controller='package', action='search', q='groups:group_00', page=2) + + res = self.app.get(url) assert 'href="/dataset?q=groups%3Agroup_00&page=1"' in res pkg_numbers = scrape_search_results(res, 'dataset') assert_equal(['30', '29', '28', '27', '26', '25', '24', '23', '22', '21', '20', '19', '18', '17', '16', '15', '14', '13', '12', '11'], pkg_numbers) def test_group_datasets_read_p1(self): - res = self.app.get(url_for(controller='group', action='read', id='group_00')) + + with self.app.flask_app.test_request_context(): + url = url_for(controller='group', action='read', id='group_00') + + res = self.app.get(url) assert 'href="/group/group_00?page=2' in res, res pkg_numbers = scrape_search_results(res, 'group_dataset') assert_equal(['50', '49', '48', '47', '46', '45', '44', '43', '42', '41', '40', '39', '38', '37', '36', '35', '34', '33', '32', '31'], pkg_numbers) def test_group_datasets_read_p2(self): - res = self.app.get(url_for(controller='group', action='read', id='group_00', page=2)) + + with self.app.flask_app.test_request_context(): + url = url_for(controller='group', action='read', id='group_00', page=2) + + res = self.app.get(url) assert 'href="/group/group_00?page=1' in res, res pkg_numbers = scrape_search_results(res, 'group_dataset') assert_equal(['30', '29', '28', '27', '26', '25', '24', '23', '22', '21', '20', '19', '18', '17', '16', '15', '14', '13', '12', '11'], pkg_numbers) @@ -101,12 +117,20 @@ def teardown_class(self): model.repo.rebuild_db() def test_group_index(self): - res = self.app.get(url_for(controller='group', action='index')) + + with self.app.flask_app.test_request_context(): + url = url_for(controller='group', action='index') + + res = self.app.get(url) assert 'href="/group?q=&sort=&page=2"' in res, res grp_numbers = scrape_search_results(res, 'group') assert_equal(['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20'], grp_numbers) - res = self.app.get(url_for(controller='group', action='index', page=2)) + + with self.app.flask_app.test_request_context(): + url = url_for(controller='group', action='index', page=2) + + res = self.app.get(url) assert 'href="/group?q=&sort=&page=1"' in res grp_numbers = scrape_search_results(res, 'group') assert_equal(['21'], grp_numbers) @@ -130,12 +154,19 @@ def teardown_class(self): model.repo.rebuild_db() def test_users_index(self): - res = self.app.get(url_for(controller='user', action='index')) + + with self.app.flask_app.test_request_context(): + url = url_for(controller='user', action='index') + + res = self.app.get(url) assert 'href="/user?q=&order_by=name&page=2"' in res user_numbers = scrape_search_results(res, 'user') assert_equal(['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'], user_numbers) - res = self.app.get(url_for(controller='user', action='index', page=2)) + with self.app.flask_app.test_request_context(): + url = url_for(controller='user', action='index', page=2) + + res = self.app.get(url) assert 'href="/user?q=&order_by=name&page=1"' in res user_numbers = scrape_search_results(res, 'user') assert_equal(['20'], user_numbers) diff --git a/ckan/tests/legacy/functional/test_preview_interface.py b/ckan/tests/legacy/functional/test_preview_interface.py index deb7aa6f965..747834446e3 100644 --- a/ckan/tests/legacy/functional/test_preview_interface.py +++ b/ckan/tests/legacy/functional/test_preview_interface.py @@ -19,14 +19,16 @@ def setup_class(cls): cls.package = model.Package.get('annakarenina') cls.resource = cls.package.resources[0] - cls.url = h.url_for(controller='package', - action='resource_read', - id=cls.package.name, - resource_id=cls.resource.id) - cls.preview_url = h.url_for(controller='package', - action='resource_datapreview', - id=cls.package.id, - resource_id=cls.resource.id) + + with cls.app.flask_app.test_request_context(): + cls.url = h.url_for(controller='package', + action='resource_read', + id=cls.package.name, + resource_id=cls.resource.id) + cls.preview_url = h.url_for(controller='package', + action='resource_datapreview', + id=cls.package.id, + resource_id=cls.resource.id) @classmethod def teardown_class(cls): @@ -35,7 +37,9 @@ def teardown_class(cls): def test_hook(self): testpackage = self.package - resource_dict = model_dictize.resource_dictize(self.resource, {'model': model}) + + with self.app.flask_app.test_request_context(): + resource_dict = model_dictize.resource_dictize(self.resource, {'model': model}) context = { 'model': model, @@ -70,10 +74,12 @@ def test_hook(self): assert self.plugin.calls['preview_templates'] == 1, self.plugin.calls # test whether the json preview is used - preview_url = h.url_for(controller='package', - action='resource_datapreview', - id=testpackage.id, - resource_id=testpackage.resources[1].id) + + with self.app.flask_app.test_request_context(): + preview_url = h.url_for(controller='package', + action='resource_datapreview', + id=testpackage.id, + resource_id=testpackage.resources[1].id) result = self.app.get(preview_url, status=200) assert 'mock-json-preview' in result.body diff --git a/ckan/tests/legacy/functional/test_revision.py b/ckan/tests/legacy/functional/test_revision.py index af0f653fa1c..5312aad7c29 100644 --- a/ckan/tests/legacy/functional/test_revision.py +++ b/ckan/tests/legacy/functional/test_revision.py @@ -90,7 +90,9 @@ def get_package(self, name): def test_read(self): anna = model.Package.by_name(u'annakarenina') rev_id = anna.revision.id - offset = url_for(controller='revision', action='read', id='%s' % rev_id) + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='revision', action='read', id='%s' % rev_id) res = self.app.get(offset) assert 'Revision %s' % rev_id in res assert 'Revision: %s' % rev_id in res @@ -132,14 +134,18 @@ def test_list_format_atom(self): # Todo: Test for first revision on last page. # Todo: Test for last revision minus 50 on second page. # Page 1. (Implied id=1) - offset = url_for(controller='revision', action='list', format='atom') + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='revision', action='list', format='atom') res = self.app.get(offset) assert '' in res, res # Todo: Better test for 'days' request param. # - fake some older revisions and check they aren't included. - offset = url_for(controller='revision', action='list', format='atom', + + with self.app.flask_app.test_request_context(): + offset = url_for(controller='revision', action='list', format='atom', days=30) res = self.app.get(offset) assert ' section' the_html = self._get_html_from_res(html) @@ -33,13 +34,13 @@ def strip_tags(self, res): '''Call strip_tags on a TestResponse object to strip any and all HTML and normalise whitespace.''' if not isinstance(res, basestring): res = res.body.decode('utf-8') - return Stripper().strip(res) + return Stripper().strip(res) def check_named_element(self, html, tag_name, *html_to_find): '''Searches in the html and returns True if it can find a particular tag and all its subtags & data which contains all the of the html_to_find''' - named_element_re = re.compile('(<(%(tag)s\w*).*?(>.*?)' % {'tag':tag_name}) + named_element_re = re.compile('(<(%(tag)s\w*).*?(>.*?)' % {'tag':tag_name}) html_str = self._get_html_from_res(html) self._check_html(named_element_re, html_str.replace('\n', ''), html_to_find) @@ -60,13 +61,14 @@ def check_tag(self, html, *html_to_find): self._check_html(self.tag_re, html, html_to_find) def _get_html_from_res(self, html): - if isinstance(html, paste.fixture.TestResponse): + if isinstance(html, (paste.fixture.TestResponse, webtest.app.TestResponse)): html_str = html.body.decode('utf8') elif isinstance(html, unicode): html_str = html elif isinstance(html, str): html_str = html.decode('utf8') else: + import ipdb; ipdb.set_trace() raise TypeError return html_str # always unicode diff --git a/ckan/tests/legacy/lib/test_alphabet_pagination.py b/ckan/tests/legacy/lib/test_alphabet_pagination.py index 97d2773c634..c3f4cdaa428 100644 --- a/ckan/tests/legacy/lib/test_alphabet_pagination.py +++ b/ckan/tests/legacy/lib/test_alphabet_pagination.py @@ -8,6 +8,7 @@ from ckan.tests.legacy import regex_related from ckan.lib.create_test_data import CreateTestData from ckan import model +from ckan.tests import helpers other = 'Other' @@ -54,7 +55,9 @@ def test_01_package_page(self): page='A', other_text=other, ) - pager = page.pager() + app = helpers._get_test_app() + with app.flask_app.test_request_context(): + pager = page.pager() assert_true( pager.startswith( '