Michael Merickel
2018-10-19 d579f2104de139e0b0fc5d6c81aabb2f826e5e54
commit | author | age
5bf23f 1 from zope.interface import Interface
CM 2
ee117e 3 from pyramid.interfaces import (
CM 4     ITraverser,
5     IAuthorizationPolicy,
6     IAuthenticationPolicy,
7     IRendererFactory,
0c29cf 8 )
49b99e 9
5bf23f 10 from pyramid.renderers import RendererHelper
95df3a 11
0c29cf 12 from pyramid.traversal import decode_path_info, split_path_info
5bf23f 13
d579f2 14 from pyramid.config.actions import action_method
5bf23f 15
0c29cf 16
5bf23f 17 class TestingConfiguratorMixin(object):
CM 18     # testing API
0c29cf 19     def testing_securitypolicy(
MM 20         self,
21         userid=None,
22         groupids=(),
23         permissive=True,
24         remember_result=None,
25         forget_result=None,
26     ):
5bf23f 27         """Unit/integration testing helper: Registers a pair of faux
CM 28         :app:`Pyramid` security policies: a :term:`authentication
29         policy` and a :term:`authorization policy`.
30
31         The behavior of the registered :term:`authorization policy`
32         depends on the ``permissive`` argument.  If ``permissive`` is
33         true, a permissive :term:`authorization policy` is registered;
34         this policy allows all access.  If ``permissive`` is false, a
35         nonpermissive :term:`authorization policy` is registered; this
36         policy denies all access.
1273d5 37
CM 38         ``remember_result``, if provided, should be the result returned by
39         the ``remember`` method of the faux authentication policy.  If it is
40         not provided (or it is provided, and is ``None``), the default value
41         ``[]`` (the empty list) will be returned by ``remember``.
42
43         ``forget_result``, if provided, should be the result returned by
44         the ``forget`` method of the faux authentication policy.  If it is
45         not provided (or it is provided, and is ``None``), the default value
46         ``[]`` (the empty list) will be returned by ``forget``.
5bf23f 47
CM 48         The behavior of the registered :term:`authentication policy`
49         depends on the values provided for the ``userid`` and
50         ``groupids`` argument.  The authentication policy will return
51         the userid identifier implied by the ``userid`` argument and
52         the group ids implied by the ``groupids`` argument when the
0184b5 53         :attr:`pyramid.request.Request.authenticated_userid` or
CM 54         :attr:`pyramid.request.Request.effective_principals` APIs are
5bf23f 55         used.
CM 56
57         This function is most useful when testing code that uses
3c2f95 58         the APIs named :meth:`pyramid.request.Request.has_permission`,
0184b5 59         :attr:`pyramid.request.Request.authenticated_userid`,
CM 60         :attr:`pyramid.request.Request.effective_principals`, and
5bf23f 61         :func:`pyramid.security.principals_allowed_by_permission`.
0b23b3 62
TL 63         .. versionadded:: 1.4
64            The ``remember_result`` argument.
65
66         .. versionadded:: 1.4
67            The ``forget_result`` argument.
5bf23f 68         """
CM 69         from pyramid.testing import DummySecurityPolicy
0c29cf 70
1273d5 71         policy = DummySecurityPolicy(
CM 72             userid, groupids, permissive, remember_result, forget_result
0c29cf 73         )
5bf23f 74         self.registry.registerUtility(policy, IAuthorizationPolicy)
CM 75         self.registry.registerUtility(policy, IAuthenticationPolicy)
1273d5 76         return policy
5bf23f 77
CM 78     def testing_resources(self, resources):
79         """Unit/integration testing helper: registers a dictionary of
80         :term:`resource` objects that can be resolved via the
81         :func:`pyramid.traversal.find_resource` API.
82
83         The :func:`pyramid.traversal.find_resource` API is called with
84         a path as one of its arguments.  If the dictionary you
85         register when calling this method contains that path as a
86         string key (e.g. ``/foo/bar`` or ``foo/bar``), the
87         corresponding value will be returned to ``find_resource`` (and
88         thus to your code) when
89         :func:`pyramid.traversal.find_resource` is called with an
90         equivalent path string or tuple.
91         """
0c29cf 92
5bf23f 93         class DummyTraverserFactory:
CM 94             def __init__(self, context):
95                 self.context = context
96
97             def __call__(self, request):
95df3a 98                 path = decode_path_info(request.environ['PATH_INFO'])
5bf23f 99                 ob = resources[path]
95df3a 100                 traversed = split_path_info(path)
0c29cf 101                 return {
MM 102                     'context': ob,
103                     'view_name': '',
104                     'subpath': (),
105                     'traversed': traversed,
106                     'virtual_root': ob,
107                     'virtual_root_path': (),
108                     'root': ob,
109                 }
110
111         self.registry.registerAdapter(
112             DummyTraverserFactory, (Interface,), ITraverser
113         )
5bf23f 114         return resources
CM 115
0c29cf 116     testing_models = testing_resources  # b/w compat
5bf23f 117
CM 118     @action_method
119     def testing_add_subscriber(self, event_iface=None):
120         """Unit/integration testing helper: Registers a
121         :term:`subscriber` which listens for events of the type
122         ``event_iface``.  This method returns a list object which is
123         appended to by the subscriber whenever an event is captured.
124
125         When an event is dispatched that matches the value implied by
126         the ``event_iface`` argument, that event will be appended to
127         the list.  You can then compare the values in the list to
128         expected event notifications.  This method is useful when
129         testing code that wants to call
130         :meth:`pyramid.registry.Registry.notify`,
131         or :func:`zope.component.event.dispatch`.
132
133         The default value of ``event_iface`` (``None``) implies a
134         subscriber registered for *any* kind of event.
135         """
136         event_iface = self.maybe_dotted(event_iface)
137         L = []
0c29cf 138
5bf23f 139         def subscriber(*event):
CM 140             L.extend(event)
0c29cf 141
5bf23f 142         self.add_subscriber(subscriber, event_iface)
CM 143         return L
144
145     def testing_add_renderer(self, path, renderer=None):
146         """Unit/integration testing helper: register a renderer at
147         ``path`` (usually a relative filename ala ``templates/foo.pt``
148         or an asset specification) and return the renderer object.
149         If the ``renderer`` argument is None, a 'dummy' renderer will
150         be used.  This function is useful when testing code that calls
151         the :func:`pyramid.renderers.render` function or
152         :func:`pyramid.renderers.render_to_response` function or
153         any other ``render_*`` or ``get_*`` API of the
154         :mod:`pyramid.renderers` module.
155
156         Note that calling this method for with a ``path`` argument
157         representing a renderer factory type (e.g. for ``foo.pt``
158         usually implies the ``chameleon_zpt`` renderer factory)
159         clobbers any existing renderer factory registered for that
160         type.
161
162         .. note:: This method is also available under the alias
163            ``testing_add_template`` (an older name for it).
164
165         """
166         from pyramid.testing import DummyRendererFactory
0c29cf 167
5bf23f 168         helper = RendererHelper(name=path, registry=self.registry)
0c29cf 169         factory = self.registry.queryUtility(
MM 170             IRendererFactory, name=helper.type
171         )
5bf23f 172         if not isinstance(factory, DummyRendererFactory):
CM 173             factory = DummyRendererFactory(helper.type, factory)
0c29cf 174             self.registry.registerUtility(
MM 175                 factory, IRendererFactory, name=helper.type
176             )
5bf23f 177
CM 178         from pyramid.testing import DummyTemplateRenderer
0c29cf 179
5bf23f 180         if renderer is None:
CM 181             renderer = DummyTemplateRenderer()
182         factory.add(path, renderer)
183         return renderer
184
185     testing_add_template = testing_add_renderer