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