def test_handle_submit_nosharingchange(self): context = testing.DummyModel(title='oldtitle', description='oldescription', default_tool='overview') context.__acl__ = ['a'] context.staff_acl = ['1'] request = testing.DummyRequest() self._register() workflow = self._registerDummyWorkflow() view = self._makeOne(context, request) converted = { 'title': u'Thetitle yo', 'description': 'thedescription', 'text': 'thetext', 'security_state': 'private', 'sendalert_default': False, 'default_tool': 'files', 'tools': [], } view.handle_submit(converted) self.assertEqual(workflow.transitioned[0]['to_state'], 'private')
def test_object_with_custom_acl_matches_object_acl(self): from repoze.lemonade.testing import registerContentFactory from repoze.workflow.testing import registerDummyWorkflow from repoze.lemonade.interfaces import IContent workflow = registerDummyWorkflow('security') from zope.interface import directlyProvides from zope.interface import Interface class IFoo(Interface): pass registerContentFactory(testing.DummyModel, IFoo) root = testing.DummyModel() root.state = 'state' acl = [] root.__acl__ = acl root.__custom_acl__ = acl directlyProvides(root, (IContent, IFoo)) L = self._callFUT(root) self.assertEqual(workflow.resetted, []) self.assertEqual(L, ['updated 0 content objects'])
def test_it_has_acl(self): from pyramid.security import Allow from pyramid.security import Deny from pyramid.security import Everyone from karl.security.policy import MEMBER_PERMS from karl.security.policy import ADMINISTRATOR_PERMS ob = testing.DummyModel() ob.docid = 1234 ob.creator = 'dummyUser' ob.__acl__ = [] index = DummyIndex() ob.catalog = {'path': index} self._callFUT(ob, None) acl = ob.__acl__ self.assertEqual(len(acl), 3) self.assertEqual(acl[0], (Allow, 'group.KarlAdmin',ADMINISTRATOR_PERMS)) self.assertEqual(acl[1], (Allow, 'dummyUser', MEMBER_PERMS)) self.assertEqual(acl[2], (Deny, Everyone, ('edit', 'delete'))) self.assertEqual(index.indexed, {1234: ob})
def setUp(self): cleanUp() # Create dummy site skel from karl.testing import DummyCommunity community = DummyCommunity() site = community.__parent__.__parent__ site.sessions = DummySessions() blog = testing.DummyModel() community["blog"] = blog blogentry = blog["foo"] = DummyBlogEntry() container = blogentry["comments"] comment = container["99"] = DummyComment('Re: foo', 'text', 'description', 'creator') self.context = comment # Create dummy request request = testing.DummyRequest() request.environ['repoze.browserid'] = '1' self.request = request registerLayoutProvider()
def test_it(self): from zope.interface import directlyProvides from pyramid.security import Allow from karl.models.interfaces import ICommunity from karl.security.policy import ADMINISTRATOR_PERMS from karl.security.policy import MEMBER_PERMS from karl.security.policy import MODERATOR_PERMS ob = testing.DummyModel() ob.__acl__ = [] index = DummyIndex() ob.catalog = {'path': index} ob.docid = 1234 directlyProvides(ob, ICommunity) ob.moderators_group_name = 'moderators' ob.members_group_name = 'members' self._callFUT(ob, None) self.assertEqual(ob.__acl__[0], (Allow, 'group.KarlAdmin', ADMINISTRATOR_PERMS)) self.assertEqual(ob.__acl__[1], (Allow, 'moderators', MODERATOR_PERMS)) self.assertEqual(ob.__acl__[2], (Allow, 'members', MEMBER_PERMS)) self.assertEqual(index.indexed, {1234: ob})
def test_community_adapter(self): from zope.interface import alsoProvides from karl.models.interfaces import ICommunityInfo context = testing.DummyModel( title='foo', number_of_members=7, ) def dummy_communityinfo_adapter(context, request): return context karl.testing.registerAdapter( dummy_communityinfo_adapter, (testing.DummyModel, testing.DummyRequest), ICommunityInfo) request = testing.DummyRequest() from karl.views.adapters import community_livesearch_result result = community_livesearch_result(context, request) self.assertEqual('foo', result['title']) self.assertEqual(7, result['num_members']) self.assertEqual('community', result['type']) self.assertEqual('community', result['category'])
def test_with_line_filter(self): container = testing.DummyModel() lines = ['a', 'b', 'c'] request = testing.DummyRequest() def line_filter(line): if line == 'c': return line batch = self._callFUT(lines, container, request, line_filter=line_filter) self.assertEqual(len(batch['entries']), 1) self.assertEqual(batch['batch_start'], 0) self.assertEqual(batch['batch_size'], 20) self.assertEqual(batch['batch_end'], 1) self.assertEqual(batch['total'], 1) self.assertEqual(batch['previous_batch'], None) self.assertEqual(batch['next_batch'], None) self.assertEqual(batch['batching_required'], False)
def test_POST_w_plugins_miss(self, remember): from pyramid.httpexceptions import HTTPFound from urlparse import urlsplit try: from urlparse import parse_qsl parse_qsl # stfu pyflakes except ImportError: # Python < 2.6 from cgi import parse_qsl request = testing.DummyRequest() request.POST['form.submitted'] = 1 request.POST['login'] = '******' request.POST['password'] = '******' context = testing.DummyModel() context.users = DummyUsers() response = self._callFUT(context, request) self.failUnless(isinstance(response, HTTPFound)) (_, _, path, query, _) = urlsplit(response.location) self.assertEqual(path, '/login.html') self.assertEqual(request.session['came_from'], 'http://example.com') query = dict(parse_qsl(query, 1, 1)) self.assertEqual(query['reason'], 'Bad username or password')
def test_comment_ordering(self): self._register() registerLayoutProvider() import datetime _NOW = datetime.datetime.now() _BEFORE = _NOW - datetime.timedelta(hours=1) context = testing.DummyModel() context.sessions = DummySessions() context.title = 'title' context['comments'] = testing.DummyModel() comment = testing.DummyModel() comment.creator = 'dummy' comment.created = _NOW comment.text = 'My dog has fleas.' context['comments']['1'] = comment comment2 = testing.DummyModel() comment2.creator = 'dummy' comment2.created = _BEFORE comment2.text = "My cat's breath smells like cat food." context['comments']['2'] = comment2 context['attachments'] = testing.DummyModel() from karl.models.interfaces import ISite from karl.content.interfaces import IForum directlyProvides(context, ISite) alsoProvides(context, IForum) context['profiles'] = profiles = testing.DummyModel() profiles['dummy'] = DummyProfile(title='Dummy Profile') request = testing.DummyRequest() request.environ['repoze.browserid'] = 1 def dummy_byline_info(context, request): return context from karl.content.views.interfaces import IBylineInfo karl.testing.registerAdapter(dummy_byline_info, (Interface, Interface), IBylineInfo) renderer = karl.testing.registerDummyRenderer( 'templates/show_forum_topic.pt') self._callFUT(context, request) self.assertEqual(len(renderer.comments), 2) self.assertEqual(renderer.comments[0]['text'], "My cat's breath smells like cat food.") self.assertEqual(renderer.comments[1]['text'], 'My dog has fleas.')
def test_handle_submit_attachment_is_None(self): """ There seems to be some set of circumstances under which formish will return a None as a value in the attachments sequence. """ from karl.models.interfaces import IObjectModifiedEvent from zope.interface import Interface from karl.models.interfaces import ITagQuery from karl.content.interfaces import IBlogEntry from repoze.lemonade.testing import registerContentFactory from karl.testing import DummyCatalog karl.testing.registerAdapter(DummyTagQuery, (Interface, Interface), ITagQuery) self._registerDummyWorkflow() context = DummyBlogEntry() context.sessions = DummySessions() context.__name__ ='ablogentry' context.catalog = DummyCatalog() context['attachments'] = testing.DummyModel() from karl.models.interfaces import ISite from zope.interface import directlyProvides directlyProvides(context, ISite) converted = {'title':'foo', 'text':'text', 'security_state':'public', 'tags':'thetesttag', 'attachments':[None], } registerContentFactory(DummyBlogEntry, IBlogEntry) L = karl.testing.registerEventListener( (Interface, IObjectModifiedEvent)) karl.testing.registerDummySecurityPolicy('testeditor') request = self._makeRequest() controller = self._makeOne(context, request) response = controller.handle_submit(converted) self.assertEqual(response.location, 'http://example.com/ablogentry/') self.assertEqual(len(L), 2) self.assertEqual(context.title, 'foo') self.assertEqual(context.text, 'text') self.assertEqual(context.modified_by, 'testeditor')
def test_replace_photo(self): from cStringIO import StringIO from karl.content.interfaces import ICommunityFile from repoze.lemonade.testing import registerContentFactory karl.testing.registerDummySecurityPolicy("userid") def make_image(title, stream, mimetype, filename, creator): res = testing.DummyModel() res.title = title res.mimetype = mimetype res.data = stream.read() res.filename = filename res.creator = creator res.is_image = True return res registerContentFactory(make_image, ICommunityFile) class DummyModel(testing.DummyModel): # Simulate repoze.folder behavior of refusing to overwrite # existing keys without an explicit removal. def __setitem__(self, name, value): if name in self: raise KeyError(u'An object named %s already exists' % name) return testing.DummyModel.__setitem__(self, name, value) context = makeRoot() context.title = 'Howdy Doody' context.__name__ = 'howdydoody' context.size = 1000 context['photo'] = testing.DummyModel() form = {'photo': DummyUpload(StringIO(one_pixel_jpeg), 'image/jpeg')} self._callFUT(context, form) self.assertTrue('photo' in context) photo = context['photo'] self.assertEqual(photo.title, 'Photo of Howdy Doody') self.assertEqual(photo.mimetype, 'image/jpeg') self.assertEqual(photo.data, one_pixel_jpeg) self.assertEqual(photo.filename, 'test.dat') self.assertEqual(photo.creator, 'userid')
def test___call__lock(self): context = testing.DummyModel() request = testing.DummyRequest() form = self._make_one(context, request) fields = form.form_fields() widgets = form.form_widgets(fields) field_names = [x[0] for x in fields] widget_names = [x[0] for x in fields] self.failIf('unlock' in field_names) self.failIf('unlock' in widget_names) import datetime lock_time = datetime.datetime.now() - datetime.timedelta(seconds=1) context.lock = {'time': lock_time, 'userid': 'foo'} form = self._make_one(context, request) fields = form.form_fields() widgets = form.form_widgets(fields) field_names = [x[0] for x in fields] widget_names = [x[0] for x in fields] self.failUnless('unlock' in field_names) self.failUnless('unlock' in widget_names)
def test_handle_submit(self): from karl.testing import DummyCatalog from repoze.lemonade.testing import registerContentFactory from karl.content.interfaces import IWikiPage from karl.utilities.interfaces import IAlerts converted = { 'title': 'wikipage', 'text': 'text', 'sendalert': True, 'security_state': 'public', 'tags': 'thetesttag', } context = testing.DummyModel() context.catalog = DummyCatalog() request = testing.DummyRequest() registerContentFactory(DummyWikiPage, IWikiPage) karl.testing.registerDummySecurityPolicy('userid') class Alerts(object): def __init__(self): self.emitted = [] def emit(self, context, request): self.emitted.append((context, request)) alerts = Alerts() karl.testing.registerUtility(alerts, IAlerts) self._registerSecurityWorkflow() controller = self._makeOne(context, request) response = controller.handle_submit(converted) wikipage = context['wikipage'] self.assertEqual(wikipage.title, 'wikipage') self.assertEqual(wikipage.text, 'text') self.assertEqual(wikipage.creator, 'userid') self.assertEqual( response.location, 'http://example.com/wikipage/?status_message=Wiki%20Page%20created' ) self.assertEqual(len(alerts.emitted), 1)
def test_handle_submit(self): from repoze.lemonade.testing import registerContentFactory from karl.content.interfaces import IForum def factory(title, desc, creator): return testing.DummyModel( title=title, description=desc, creator=creator) registerContentFactory(factory, IForum) converted = { 'title': 'title', 'description': 'desc', 'security_state': 'public'} context = testing.DummyModel() request = testing.DummyRequest() workflow = self._registerDummyWorkflow() controller = self._makeOne(context, request) response = controller.handle_submit(converted) self.assertEqual(response.location, 'http://example.com/title/') self.assertEqual(context['title'].title, 'title') self.assertEqual(context['title'].description, 'desc') self.assertEqual(context['title'].creator, None) self.assertEqual(workflow.initialized, True)
def test_reindex_with_indexes(self): a = testing.DummyModel() L = [] objectmap = DummyObjectMap({1: [a, (u'', u'a')]}) transaction = DummyTransaction() inst = self._makeOne() inst.transaction = transaction site = _makeSite(catalog=inst, objectmap=objectmap) site['a'] = a inst.objectids = [1] index = DummyIndex() inst['index'] = index self.config.registry._substanced_indexes = {'index':index} index.reindex_doc = lambda objectid, model: L.append((objectid, model)) out = [] inst.reindex(indexes=('index',), output=out.append) self.assertEqual(out, ["reindexing only indexes ('index',)", 'reindexing /a', '*** committing ***']) self.assertEqual(transaction.committed, 1) self.assertEqual(L, [(1,a)])
def test_file_adapter(self): from datetime import datetime from karl.content.views.interfaces import IFileInfo context = testing.DummyModel( title='foo', modified_by='susan', modified=datetime(1985, 1, 1), ) request = testing.DummyRequest() karl.testing.registerAdapter( DummyFileAdapter, (testing.DummyModel, testing.DummyRequest), IFileInfo) from karl.views.adapters import file_livesearch_result result = file_livesearch_result(context, request) self.assertEqual('foo', result['title']) self.assertEqual('susan', result['modified_by']) self.assertEqual('1985-01-01T00:00:00', result['modified']) self.assertEqual('file', result['type']) self.assertEqual('file', result['category']) self.assertEqual(None, result['community']) self.failUnless(result['icon'].endswith('/imgpath.png'))
def test_with_filename_too_big(self): from karl.testing import registerSettings from karl.content.interfaces import ICommunityFile from StringIO import StringIO registerSettings(upload_limit=1) attachments = [ DummyFile(filename='abc', mimetype='text/plain', file=StringIO('abc')) ] folder = testing.DummyModel() from repoze.lemonade.testing import registerContentFactory class BigDummyFile(object): def __init__(self, **kw): self.__dict__.update(kw) self.size = 10000 registerContentFactory(BigDummyFile, ICommunityFile) request = testing.DummyRequest() self.assertRaises(ValueError, self._callFUT, attachments, folder, 'chris', request)
def test_show_workflow_custom_acl(self): from repoze.workflow.testing import DummyWorkflow from zope.interface import Interface from zope.interface import directlyProvides workflow = DummyWorkflow() def state_info(context, request): return [{ 'name': 'foo', 'current': True, 'transitions': True }, { 'name': 'bar', 'current': False, 'transitions': True }] workflow.state_info = state_info def get_dummy_workflow(*args, **kw): return workflow import karl.views.acl old_f = karl.views.acl.get_context_workflow karl.views.acl.get_context_workflow = get_dummy_workflow try: context = testing.DummyModel() context.state = 'foo' context.__custom_acl__ = [] directlyProvides(Interface) request = testing.DummyRequest() renderer = karl.testing.registerDummyRenderer( 'templates/edit_acl.pt') self._callFUT(context, request) self.assertEqual(renderer.security_state, 'CUSTOM') self.assertEqual(renderer.security_states, ['CUSTOM', 'foo', 'bar']) finally: karl.views.acl.get_context_workflow = old_f
def test_empty_category_description(self): xml = """ <peopledirectory> <categories> <category name="offices" title="Offices"> <value name="nyc" title="NYC"> </value> </category> </categories> </peopledirectory> """ elem = parse_xml(xml) site = testing.DummyModel(list_aliases={}) peopledir = site['people'] = DummyPeopleDirectory() peopledir['categories']['bogus'] = object() self._callFUT(peopledir, elem) self.failIf('bogus' in peopledir['categories']) category = peopledir['categories']['offices']['nyc'] self.assertEqual(category.description, '')
def test_update_indexes_remove_single(self): self._setup_index() registry = self.config.registry out = [] inst = self._makeOne() transaction = DummyTransaction() inst.transaction = transaction existing = testing.DummyModel() existing.sd_category = 'system' inst['other'] = existing inst.update_indexes('system', registry=registry, output=out.append) self.assertEqual(out, [ "update_indexes: starting category 'system'", "update_indexes: adding field index named 'name'", "update_indexes: removing index named u'other'", '*** committing ***', 'update_indexes: not reindexing added indexes', "update_indexes: finished with category 'system'" ]) self.assertEqual(transaction.committed, 1) self.assertEqual(transaction.aborted, 0) self.assertTrue('name' in inst)
def test_get_info_alpha(self): request = testing.DummyRequest() context = testing.DummyModel() context.alpha = {'A':1} from zope.interface import directlyProvides directlyProvides(context, DummyInterface) adapter = self._makeOne(context) letters = adapter.get_info(request) self.assertEqual(len(letters), 27) self.assertEqual(letters[0]['name'], 'A') self.assertEqual(letters[0]['css_class'], 'notcurrent') self.assertEqual(letters[0]['href'], 'http://example.com?titlestartswith=A') self.assertEqual(letters[0]['is_current'], False) self.assertEqual(letters[1]['name'], 'B') self.assertEqual(letters[1]['css_class'], 'notcurrent') self.assertEqual(letters[1]['href'], None) self.assertEqual(letters[1]['is_current'], False) self.assertEqual(letters[26]['name'], 'Any') self.assertEqual(letters[26]['css_class'], 'current') self.assertEqual(letters[26]['href'], None) self.assertEqual(letters[26]['is_current'], True)
def test_including_replace_image_fail(self): import simplejson context = testing.DummyModel() request = testing.DummyRequest(params={ 'include_image_url': '/badimage', 'source': 'myrecent', }) response = self._call_fut(context, request) self.assertEqual(response.status, '200 OK') self.assertEqual(self.dummy_get_images_batch.called, (context, request, { 'community': None, 'batch_start': 0, 'batch_size': 12, 'creator': None })) data = simplejson.loads(response.body) self.assertEqual(data['images_info'], { 'totalRecords': 5, 'start': 0, 'records': ['foo', 'bar'], })
def test_upload_tempfolder(self): import simplejson karl.testing.registerDummySecurityPolicy('chris') context = testing.DummyModel() request = testing.DummyRequest(params={ 'file': DummyUpload(), 'title': 'Title', }) response = self._call_fut(context, request) self.assertEqual(response.status, '200 OK') data = simplejson.loads(response.body) self.assertEqual(data['upload_image_info'], {'title': 'Foo'}) self.assert_('images_info' not in data) image = context['TEMP'].values()[0] self.assertEqual(image.title, 'Title') self.assert_(len(image.image().fp.read()) > 0) self.assertEqual(image.mimetype, 'image/jpeg') self.assertEqual(image.filename, 'test.jpg') self.assertEqual(image.creator, 'chris') self.failUnless(hasattr(image, 'modified')) self.assertEqual(self.workflow.initialized, [])
def test_authenticated_realm_does_not_match(self): request = testing.DummyRequest(authorization=('Negotiate', 'ticket'), context=testing.DummyModel()) request.context.users = DummyUsers() request.registry.settings = {} request.registry.settings['kerberos.user_finder'] = \ 'karl.security.kerberos_auth.login_user_finder' request.registry.settings['kerberos.allowed_realms'] = \ 'foo examplerealm' request.registry.settings['kerberos.allowed_domains'] = \ 'foo exampledomain' self.kerberos.authGSSServerInit.return_value = 1, 'context' self.kerberos.authGSSServerStep.return_value = 1 self.kerberos.authGSSServerUserName.return_value = \ 'joey\\exampledomain@anotherrealm' self.assertEqual(self.call_fut(request), None) self.kerberos.authGSSServerInit.assert_called_once_with( '*****@*****.**') self.kerberos.authGSSServerStep.assert_called_once_with( 'context', 'ticket') self.kerberos.authGSSServerUserName.assert_called_once_with('context') self.kerberos.authGSSServerClean.assert_called_once_with('context')
def test_handle_submit_changetools(self): context = testing.DummyModel(title='oldtitle', default_tool='overview') request = testing.DummyRequest() blog_tool_factory = DummyToolFactory(present=True) calendar_tool_factory = DummyToolFactory(present=False) self._registerAddables([ {'name':'blog', 'title':'blog', 'component':blog_tool_factory}, {'name':'calendar', 'title':'calendar', 'component':calendar_tool_factory}]) self._register() view = self._makeOne(context, request) converted = {'title':u'Thetitle yo', 'description':'thedescription', 'text':'thetext', 'security_state':'public', 'calendar':'calendar', 'default_tool': 'overview', 'tools':['calendar'], } view.handle_submit(converted) self.assertEqual(blog_tool_factory.removed, True) self.assertEqual(calendar_tool_factory.added, True)
def test_handle_submit(self): converted = { 'title': 'newtitle', 'description': 'newdescription', } context = testing.DummyModel(title='oldtitle', description='olddescription') context.catalog = DummyCatalog() from karl.models.interfaces import IObjectModifiedEvent L = karl.testing.registerEventListener( (Interface, IObjectModifiedEvent)) karl.testing.registerDummySecurityPolicy('testeditor') request = testing.DummyRequest() controller = self._makeOne(context, request) response = controller.handle_submit(converted) self.assertEqual(L[0], context) self.assertEqual(L[1].object, context) self.assertEqual(response.location, 'http://example.com/?status_message=Forum+Edited') self.assertEqual(context.title, 'newtitle') self.assertEqual(context.description, 'newdescription') self.assertEqual(context.modified_by, 'testeditor')
def test_numresults_withkind(self): from repoze.lemonade.testing import registerListItem from karl.models.interfaces import IGroupSearchFactory from karl.views.interfaces import ILiveSearchEntry def dummy_factory(context, request, term): return DummyGroupSearchFactory( lambda x: testing.DummyModel(title='yo')) registerListItem(IGroupSearchFactory, dummy_factory, 'foo_kind', title='Dummy') context = testing.DummyModel() request = testing.DummyRequest() request.params = { 'val': 'somesearch', 'kind': 'foo_kind', } def dummy_adapter(context, request): return dict(title=context.title) karltesting.registerAdapter(dummy_adapter, (testing.DummyModel, testing.DummyRequest), ILiveSearchEntry) results = self._callFUT(context, request) self.assertEqual(len(results), 20)
def test_handle_submit(self): from schemaish.type import File as SchemaFile from karl.models.interfaces import IObjectModifiedEvent from zope.interface import Interface from karl.models.interfaces import ITagQuery from karl.content.interfaces import IBlogEntry from repoze.lemonade.testing import registerContentFactory from karl.testing import DummyCatalog karl.testing.registerAdapter(DummyTagQuery, (Interface, Interface), ITagQuery) self._registerDummyWorkflow() context = DummyBlogEntry() context.sessions = DummySessions() context.__name__ = 'ablogentry' context.catalog = DummyCatalog() context['attachments'] = testing.DummyModel() from karl.models.interfaces import ISite from zope.interface import directlyProvides directlyProvides(context, ISite) converted = { 'title': 'foo', 'text': 'text', 'security_state': 'public', 'tags': 'thetesttag', 'attachments': [SchemaFile(None, None, None)], } registerContentFactory(DummyBlogEntry, IBlogEntry) L = karl.testing.registerEventListener( (Interface, IObjectModifiedEvent)) karl.testing.registerDummySecurityPolicy('testeditor') request = self._makeRequest() controller = self._makeOne(context, request) response = controller.handle_submit(converted) self.assertEqual(response.location, 'http://example.com/ablogentry/') self.assertEqual(len(L), 2) self.assertEqual(context.title, 'foo') self.assertEqual(context.text, 'text') self.assertEqual(context.modified_by, 'testeditor')
def test_with_kind_without_body(self): from karl.models.interfaces import ICatalogSearch from karl.models.interfaces import IGroupSearchFactory from repoze.lemonade.testing import registerListItem from webob.multidict import MultiDict def dummy_factory(context, request, term): def results(): return 0, [], None results.criteria = {'foo': 'bar'} return results registerListItem(IGroupSearchFactory, dummy_factory, 'dummy1', title='Dummy1', sort_key=1) karltesting.registerAdapter(DummySearch, (Interface), ICatalogSearch) request = testing.DummyRequest(params=MultiDict({'kind': 'dummy1'})) context = testing.DummyModel() result = self._callFUT(context, request) self.assertEqual(result[0]['total'], 1)
def test_with_kind_with_body(self): from karl.models.interfaces import ICatalogSearch from karl.models.interfaces import IGroupSearchFactory from repoze.lemonade.testing import registerListItem from webob.multidict import MultiDict content = DummyContent() def search_factory(*arg, **kw): return DummySearchFactory(content) registerListItem(IGroupSearchFactory, search_factory, 'dummy1', title='Dummy1', sort_key=1) karltesting.registerAdapter(DummySearch, (Interface), ICatalogSearch) request = testing.DummyRequest(params=MultiDict({ 'body': 'yo', 'kind': 'dummy1' })) context = testing.DummyModel() result = self._callFUT(context, request) self.assertEqual(result[0]['total'], 1)