1
2from zope.interface import implements
3from twisted.python import log
4from twisted.internet import defer
5from nevow import appserver, context, inevow, loaders, rend, tags as T, testutil
6
7
8class Root(rend.Page):
9    docFactory = loaders.stan(T.html[T.p['Root']])
10
11
12
13class NotFoundHandler(object):
14    implements(inevow.ICanHandleNotFound)
15    html = 'NotFoundHandler'
16    def renderHTTP_notFound(self, ctx):
17        return self.html
18
19class BrokenException(Exception):
20    pass
21
22class BadNotFoundHandler(object):
23    implements(inevow.ICanHandleNotFound)
24    html = 'NotFoundHandler'
25    exceptionType = BrokenException
26    exceptionMessage ='Error from BadNotFoundHandler'
27    def __init__(self, exceptionType=None):
28        if exceptionType is not None:
29            self.exceptionType = exceptionType
30    def renderHTTP_notFound(self, ctx):
31        raise self.exceptionType(self.exceptionMessage)
32
33
34def getResource(root, path):
35    ctx = context.RequestContext(tag=testutil.FakeRequest(uri=path))
36    return appserver.NevowSite(root).getPageContextForRequestContext(ctx).addCallback(
37        lambda newctx: newctx.tag)
38
39def renderResource(uri, notFoundHandler=None):
40    """Render a resource at some uri and return the response code and html.
41    """
42
43    root = Root()
44    if notFoundHandler is not None:
45        root.remember(notFoundHandler, inevow.ICanHandleNotFound)
46    site = appserver.NevowSite(root)
47    ctx = context.SiteContext(tag=site)
48
49    request = testutil.FakeRequest(uri=uri)
50    ctx = context.RequestContext(parent=ctx, tag=request)
51
52    def waitmore(newctx):
53        return defer.maybeDeferred(newctx.tag.renderHTTP, newctx).addCallback(lambda html: (request.code, html))
54    return site.getPageContextForRequestContext(ctx).addCallback(waitmore)
55
56
57class Test404(testutil.TestCase):
58
59    def test_standard404(self):
60        """Test the standard 404 handler.
61        """
62        root = Root()
63        def later(resource):
64            self.failUnless(isinstance(resource, rend.FourOhFour))
65            def morelater((code, html)):
66                self.assertEquals(rend.FourOhFour.notFound, html)
67                self.assertEquals(code, 404)
68            return renderResource('/foo').addCallback(morelater)
69        return getResource(root, '/foo').addCallback(later)
70
71    def test_remembered404Handler(self):
72        def later((code, html)):
73            self.assertEquals(html, NotFoundHandler.html)
74            self.assertEquals(code, 404)
75
76        return renderResource('/foo', notFoundHandler=NotFoundHandler()).addCallback(later)
77
78    def test_keyErroringNotFoundHandler(self):
79        def later((code, html)):
80            self.assertEquals(rend.FourOhFour.notFound, html)
81            self.assertEquals(code, 404)
82            fe = self.flushLoggedErrors(BrokenException)
83            self.assertEquals(len(fe), 1)
84        return renderResource('/foo', notFoundHandler=BadNotFoundHandler()).addCallback(later)
85
86