Skip to content

Commit

Permalink
100% coverage for ifacemodule/menu.py
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed May 18, 2017
1 parent 86fbd94 commit 68b3711
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 12 deletions.
1 change: 1 addition & 0 deletions .coveragerc
Expand Up @@ -5,3 +5,4 @@ source = src
exclude_lines =
pragma: no cover
if __name__ == '__main__':
raise NotImplementedError
14 changes: 8 additions & 6 deletions src/zope/app/apidoc/ifacemodule/menu.py
Expand Up @@ -16,10 +16,12 @@
"""
__docformat__ = 'restructuredtext'
import operator
from zope.security.proxy import removeSecurityProxy
import re

whitepattern = re.compile(r'\s{2,}')
namegetter = operator.itemgetter('name')

def getAllTextOfInterface(iface):
"""Get all searchable text from an interface"""
Expand Down Expand Up @@ -50,11 +52,11 @@ def findInterfaces(self):
for name, iface in self.context.items():
if (search_str in name or
(not name_only and search_str in getAllTextOfInterface(iface))):
results.append(
{'name': name,
results.append({
'name': name,
'url': './%s/index.html' %name
})
results.sort(key=lambda x: x['name'])
})
results.sort(key=namegetter)
return results

def findAllInterfaces(self):
Expand All @@ -66,11 +68,11 @@ def findAllInterfaces(self):
for name, iface in self.context.items():
results.append({
'name': name,
'url': './%s/index.html' %name,
'url': './%s/index.html' % name,
'counter': counter,
'doc': whitepattern.sub(' ', getAllTextOfInterface(iface))
})
counter += 1

results.sort(key=lambda x: x['name'])
results.sort(key=namegetter)
return results
13 changes: 13 additions & 0 deletions src/zope/app/apidoc/ifacemodule/tests.py
Expand Up @@ -53,6 +53,19 @@ def testInterfaceDetailsView(self):
self.assertIn('/++apidoc++/Code/zope/app/apidoc'
'/ifacemodule/ifacemodule/index.html', body)

def testStaticMenu(self):
response = self.publish(
'/++apidoc++/Interface/staticmenu.html',
basic='mgr:mgrpw')

self.assertEqual(response.getStatus(), 200)
body = response.getBody()
self.assertIn(
'zope.app.apidoc.interfaces.IDocumentationModule', body)
self.checkForBrokenLinks(body, '/++apidoc++/Interface/staticmenu.html',
basic='mgr:mgrpw',
# This page is slow, only do a few
max_links=5)

def test_suite():

Expand Down
24 changes: 23 additions & 1 deletion src/zope/app/apidoc/tests.py
Expand Up @@ -92,7 +92,8 @@ def tearDown(self):
super(BrowserTestCase, self).tearDown()


def checkForBrokenLinks(self, orig_response, path, basic=None):
def checkForBrokenLinks(self, orig_response, path,
basic=None, max_links=None):
response = self.publish(path, basic=basic)
links = response.html.find_all('a')

Expand All @@ -117,6 +118,11 @@ def checkForBrokenLinks(self, orig_response, path, basic=None):
seen.add(href)
self.publish(href, basic=basic)

if max_links is not None:
max_links -= 1
if not max_links:
break

def publish(self, path, basic=None, form=None, headers=None, env=None):
assert basic
self._testapp.authorization = ('Basic', tuple(basic.split(':')))
Expand Down Expand Up @@ -157,6 +163,22 @@ def test_iconviewfactory(self):
data = getViewFactoryData(factory)
self.assertEqual(data['resource'], factory.rname)

class TestUtilities(unittest.TestCase):

@unittest.skipUnless(str is bytes, "Only on py2")
def test_slot_methods(self):
from zope.app.apidoc.utilities import getFunctionSignature
self.assertEqual("(<unknown>)", getFunctionSignature(object.__init__))

@unittest.skipUnless(str is bytes, "Only on py2")
def test_unpack_methods(self):
from zope.app.apidoc.utilities import getFunctionSignature
import six

six.exec_("def f((a, b)): pass")

self.assertEqual("((a, b))", getFunctionSignature(locals()['f']))

# Generally useful classes and functions

@implementer(IContainmentRoot)
Expand Down
6 changes: 3 additions & 3 deletions src/zope/app/apidoc/utilities.py
Expand Up @@ -251,7 +251,7 @@ def getFunctionSignature(func, ignore_self=False):
# Make sure the name is a string
if isinstance(name, (tuple, list)):
name = '(' + ', '.join(name) + ')'
elif not isinstance(name, str):
elif not isinstance(name, str): # pragma: no cover
name = repr(name)

if default is placeholder:
Expand Down Expand Up @@ -370,10 +370,10 @@ def renderText(text, module=None, format=None, dedent=True):

assert format in _format_dict.values()

text = dedentString(text)

if isinstance(text, bytes):
text = text.decode('latin-1', 'replace')

text = dedentString(text)
source = createObject(format, text)

renderer = getMultiAdapter((source, TestRequest()))
Expand Down
9 changes: 7 additions & 2 deletions src/zope/app/apidoc/utilities.rst
Expand Up @@ -766,12 +766,17 @@ used. Clearly, you cannot specify both, the `module` and `format` argument.

You specify the format as follows:

>>> utilities.renderText('Hello!\n', format='zope.source.rest')
>>> utilities.renderText(u'Hello!\n', format='zope.source.rest')
u'<p>Hello!</p>\n'

Note that the format string must be a valid source factory id; if the factory
id is not given, 'zope.source.stx' is used. Thus, specifying the module is
often safer (if available):

>>> utilities.renderText('Hello!\n', module=apidoc)
>>> utilities.renderText(u'Hello!\n', module=apidoc)
u'<p>Hello!</p>\n'

Byte input is accepted, so long as it can be decoded:

>>> utilities.renderText(b'Hello!\n', module=apidoc)
u'<p>Hello!</p>\n'

0 comments on commit 68b3711

Please sign in to comment.