Exemplo n.º 1
0
class PrepareIDNNameTests(unittest.TestCase):
    """
    Tests for L{wokkel.generic.prepareIDNName}.
    """

    suppress = [
        SUPPRESS(category=DeprecationWarning,
                 message=re.escape(
                     deprecate.getDeprecationWarningString(
                         generic.prepareIDNName,
                         Version("wokkel", 18, 0, 0),
                         replacement="unicode.encode('idna')")))
    ]

    def test_deprecated(self):
        """
        prepareIDNName is deprecated.
        """
        self.callDeprecated(
            (Version("wokkel", 18, 0, 0), "unicode.encode('idna')"),
            generic.prepareIDNName, ("example.com"))

    test_deprecated.suppress = []

    def test_unicode(self):
        """
        A unicode all-ASCII name is converted to an ASCII byte string.
        """
        name = u"example.com"
        result = generic.prepareIDNName(name)
        self.assertEqual(b"example.com", result)

    def test_unicodeNonASCII(self):
        """
        A unicode with non-ASCII is converted to its ACE equivalent.
        """
        name = u"\u00e9chec.example.com"
        result = generic.prepareIDNName(name)
        self.assertEqual(b"xn--chec-9oa.example.com", result)

    def test_unicodeHalfwidthIdeographicFullStop(self):
        """
        Exotic dots in unicode names are converted to Full Stop.
        """
        name = u"\u00e9chec.example\uff61com"
        result = generic.prepareIDNName(name)
        self.assertEqual(b"xn--chec-9oa.example.com", result)

    def test_unicodeTrailingDot(self):
        """
        Unicode names with trailing dots retain the trailing dot.

        L{encodings.idna.ToASCII} doesn't allow the empty string as the input,
        hence the implementation needs to strip a trailing dot, and re-add it
        after encoding the labels.
        """
        name = u"example.com."
        result = generic.prepareIDNName(name)
        self.assertEqual(b"example.com.", result)
Exemplo n.º 2
0
def deprecatedDeferredGenerator(f):
    """
    Calls L{deferredGenerator} while suppressing the deprecation warning.

    @param f: Function to call
    @return: Return value of function.
    """
    return runWithWarningsSuppressed([
        SUPPRESS(message="twisted.internet.defer.deferredGenerator was "
                 "deprecated")
    ], deferredGenerator, f)
Exemplo n.º 3
0
class PublicNavAthenaLivePageTestCase(_PublicAthenaLivePageTestMixin,
                                      TestCase):
    """
    Tests for L{PublicNavAthenaLivePage}.
    """
    suppress = [SUPPRESS(category=DeprecationWarning)]

    def createPage(self, forUser):
        return PublicNavAthenaLivePage(self.siteStore,
                                       TestFragment(),
                                       forUser=forUser)
Exemplo n.º 4
0
class LoopbackTestCase(LoopbackTestCaseMixin, unittest.TestCase):
    loopbackFunc = staticmethod(loopback.loopback)

    def testRegularFunction(self):
        """
        Suppress loopback deprecation warning.
        """
        return LoopbackTestCaseMixin.testRegularFunction(self)
    testRegularFunction.suppress = [
        SUPPRESS(message="loopback\(\) is deprecated",
                 category=DeprecationWarning)]
Exemplo n.º 5
0
def _getDeprecationSuppression(f):
    """
    Returns a tuple of arguments needed to suppress deprecation warnings from
    a specified function.

    @param f: function to suppress dperecation warnings for
    @type f: L{callable}

    @return: tuple to add to C{suppress} attribute
    """
    return SUPPRESS(category=DeprecationWarning,
                    message='%s was deprecated' % (fullyQualifiedName(f), ))
Exemplo n.º 6
0
class DeprecationTests(TestCase):
    """
    Tests for deprecations in C{twisted.python.util}.
    """

    def test_getPluginDirs(self):
        """
        L{util.getPluginDirs} is deprecated.
        """
        util.getPluginDirs()
        currentWarnings = self.flushWarnings(
            offendingFunctions=[self.test_getPluginDirs]
        )
        self.assertEqual(
            currentWarnings[0]["message"],
            "twisted.python.util.getPluginDirs is deprecated since Twisted " "12.2.",
        )
        self.assertEqual(currentWarnings[0]["category"], DeprecationWarning)
        self.assertEqual(len(currentWarnings), 1)

    def test_addPluginDir(self):
        """
        L{util.addPluginDir} is deprecated.
        """
        util.addPluginDir()
        currentWarnings = self.flushWarnings(
            offendingFunctions=[self.test_addPluginDir]
        )
        self.assertEqual(
            currentWarnings[0]["message"],
            "twisted.python.util.addPluginDir is deprecated since Twisted " "12.2.",
        )
        self.assertEqual(currentWarnings[0]["category"], DeprecationWarning)
        self.assertEqual(len(currentWarnings), 1)

    test_addPluginDir.suppress = [  # type: ignore[attr-defined]
        SUPPRESS(
            category=DeprecationWarning,
            message="twisted.python.util.getPluginDirs is deprecated",
        )
    ]
Exemplo n.º 7
0
class DeprecationTests(unittest.TestCase):
    """
    Tests for deprecations in C{twisted.python.util}.
    """
    def test_getPluginDirs(self):
        """
        L{util.getPluginDirs} is deprecated.
        """
        util.getPluginDirs()
        currentWarnings = self.flushWarnings(
            offendingFunctions=[self.test_getPluginDirs])
        self.assertEqual(
            currentWarnings[0]['message'],
            "twisted.python.util.getPluginDirs is deprecated since Twisted "
            "12.2.")
        self.assertEqual(currentWarnings[0]['category'], DeprecationWarning)
        self.assertEqual(len(currentWarnings), 1)

    def test_addPluginDir(self):
        """
        L{util.addPluginDir} is deprecated.
        """
        util.addPluginDir()
        currentWarnings = self.flushWarnings(
            offendingFunctions=[self.test_addPluginDir])
        self.assertEqual(
            currentWarnings[0]['message'],
            "twisted.python.util.addPluginDir is deprecated since Twisted "
            "12.2.")
        self.assertEqual(currentWarnings[0]['category'], DeprecationWarning)
        self.assertEqual(len(currentWarnings), 1)

    test_addPluginDir.suppress = [
        SUPPRESS(category=DeprecationWarning,
                 message="twisted.python.util.getPluginDirs is deprecated")
    ]
Exemplo n.º 8
0
from twisted.web.error import (FlattenerError, MissingTemplateLoader,
    MissingRenderMethod)

from twisted.web.template import renderElement
from twisted.web._element import UnexposedMethodError
from twisted.web.test._util import FlattenTestCase
from twisted.web.test.test_web import DummyRequest
from twisted.web.server import NOT_DONE_YET

from twisted.python.compat import NativeStringIO as StringIO
from twisted.logger import globalLogPublisher
from twisted.test.proto_helpers import EventLoggingObserver


_xmlFileSuppress = SUPPRESS(category=DeprecationWarning,
        message="Passing filenames or file objects to XMLFile is "
                "deprecated since Twisted 12.1.  Pass a FilePath instead.")


class TagFactoryTests(TestCase):
    """
    Tests for L{_TagFactory} through the publicly-exposed L{tags} object.
    """
    def test_lookupTag(self):
        """
        HTML tags can be retrieved through C{tags}.
        """
        tag = tags.a
        self.assertEqual(tag.tagName, "a")

Exemplo n.º 9
0
class DeferredGeneratorTests(BaseDefgenTests, unittest.TestCase):

    # First provide all the generator impls necessary for BaseDefgenTests
    @deprecatedDeferredGenerator
    def _genBasics(self):

        x = waitForDeferred(getThing())
        yield x
        x = x.getResult()

        self.assertEqual(x, "hi")

        ow = waitForDeferred(getOwie())
        yield ow
        try:
            ow.getResult()
        except ZeroDivisionError as e:
            self.assertEqual(str(e), "OMG")
        yield "WOOSH"
        return

    @deprecatedDeferredGenerator
    def _genBuggy(self):
        yield waitForDeferred(getThing())
        1 // 0

    @deprecatedDeferredGenerator
    def _genNothing(self):
        if False:
            yield 1  # type: ignore[unreachable]

    @deprecatedDeferredGenerator
    def _genHandledTerminalFailure(self):
        x = waitForDeferred(
            defer.fail(TerminalException("Handled Terminal Failure")))
        yield x
        try:
            x.getResult()
        except TerminalException:
            pass

    @deprecatedDeferredGenerator
    def _genHandledTerminalAsyncFailure(self, d):
        x = waitForDeferred(d)
        yield x
        try:
            x.getResult()
        except TerminalException:
            pass

    def _genStackUsage(self):
        for x in range(5000):
            # Test with yielding a deferred
            x = waitForDeferred(defer.succeed(1))
            yield x
            x = x.getResult()
        yield 0

    _genStackUsage = deprecatedDeferredGenerator(_genStackUsage)

    def _genStackUsage2(self):
        for x in range(5000):
            # Test with yielding a random value
            yield 1
        yield 0

    _genStackUsage2 = deprecatedDeferredGenerator(_genStackUsage2)

    # Tests unique to deferredGenerator

    def testDeferredYielding(self):
        """
        Ensure that yielding a Deferred directly is trapped as an
        error.
        """

        # See the comment _deferGenerator about d.callback(Deferred).
        def _genDeferred():
            yield getThing()

        _genDeferred = deprecatedDeferredGenerator(_genDeferred)

        return self.assertFailure(_genDeferred(), TypeError)

    suppress = [
        SUPPRESS(message="twisted.internet.defer.waitForDeferred was "
                 "deprecated")
    ]
Exemplo n.º 10
0
Arquivo: detests.py Projeto: DT021/wau
class DeferredTests(unittest.TestCase):
    touched = False

    def _cb_fail(self, reason):
        self.fail(reason)

    def _cb_error(self, reason):
        raise RuntimeError(reason)

    def _cb_skip(self, reason):
        raise unittest.SkipTest(reason)

    def _touchClass(self, ignored):
        self.__class__.touched = True

    def setUp(self):
        self.__class__.touched = False

    def test_pass(self):
        return defer.succeed('success')

    def test_passGenerated(self):
        self._touchClass(None)
        yield None
    test_passGenerated = runWithWarningsSuppressed(
        [ SUPPRESS(message="twisted.internet.defer.deferredGenerator was "
                          "deprecated") ],
        defer.deferredGenerator, test_passGenerated)


    @defer.inlineCallbacks
    def test_passInlineCallbacks(self):
        """
        Test case that is decorated with L{defer.inlineCallbacks}.
        """
        self._touchClass(None)
        yield None

    def test_fail(self):
        return defer.fail(self.failureException('I fail'))

    def test_failureInCallback(self):
        d = defer.succeed('fail')
        d.addCallback(self._cb_fail)
        return d

    def test_errorInCallback(self):
        d = defer.succeed('error')
        d.addCallback(self._cb_error)
        return d

    def test_skip(self):
        d = defer.succeed('skip')
        d.addCallback(self._cb_skip)
        d.addCallback(self._touchClass)
        return d

    def test_thread(self):
        return threads.deferToThread(lambda : None)

    def test_expectedFailure(self):
        d = defer.succeed('todo')
        d.addCallback(self._cb_error)
        return d
    test_expectedFailure.todo = "Expected failure"
Exemplo n.º 11
0
from axiom.dependency import installOn
from axiom.test.util import QueryCounter

from xmantissa.webapp import PrivateApplication
from xmantissa.ixmantissa import IWebTranslator, IColumn
from xmantissa.error import Unsortable

from xmantissa.scrolltable import (InequalityModel, ScrollableView,
                                   ScrollingFragment, ScrollingElement,
                                   SequenceScrollingFragment,
                                   StoreIDSequenceScrollingFragment,
                                   AttributeColumn, UnsortableColumnWrapper,
                                   UnsortableColumn)

_unsortableColumnSuppression = SUPPRESS(message=escape(
    "Use UnsortableColumnWrapper(AttributeColumn(*a, **kw)) "
    "instead of UnsortableColumn(*a, **kw)."),
                                        category=DeprecationWarning)


class DataThunk(Item):
    a = integer()
    b = integer()
    c = text()


class DataThunkWithIndex(Item):
    """
    Another testing utility, similar to L{DataThunk}, but with an indexed
    attribute, so that sorting complexity is independent of the number of
    instances which exist, so that performance testing can be done.
    """
Exemplo n.º 12
0
class TestPage(unittest.TestCase):
    def test_simple(self):
        xhtml = '<ul id="nav"><li>one</li><li>two</li><li>three</li></ul>'
        r = rend.Page(docFactory=loaders.htmlstr(xhtml))
        return deferredRender(r).addCallback(
            lambda result: self.assertEqual(result, xhtml))

    test_simple.suppress = [
        SUPPRESS(message=r"\[v0.8\] htmlstr is deprecated because it's buggy. "
                 "Please start using xmlfile and/or xmlstr.")
    ]

    def test_extend(self):
        xhtml = '<ul id="nav"><li>one</li><li>two</li><li>three</li></ul>'

        class R(rend.Page):
            docFactory = loaders.htmlstr(xhtml)

        r = R()
        return deferredRender(r).addCallback(
            lambda result: self.assertEqual(result, xhtml))

    test_extend.suppress = [
        SUPPRESS(message=r"\[v0.8\] htmlstr is deprecated because it's buggy. "
                 "Please start using xmlfile and/or xmlstr.")
    ]

    def test_data(self):
        xhtml = ('<ul id="nav" nevow:data="numbers" nevow:render="sequence">'
                 '<li nevow:pattern="item" nevow:render="string">number</li>'
                 '</ul>')

        class R(rend.Page):
            docFactory = loaders.htmlstr(xhtml)

            def data_numbers(self, context, data):
                return ['one', 'two', 'three']

        r = R()
        return deferredRender(r).addCallback(lambda result: self.assertEqual(
            result, '<ul id="nav"><li>one</li><li>two</li><li>three</li></ul>')
                                             )

    test_data.suppress = [
        SUPPRESS(message=r"\[v0.8\] htmlstr is deprecated because it's buggy. "
                 "Please start using xmlfile and/or xmlstr.")
    ]

    def test_noData(self):
        """Test when data is missing, i.e. self.original is None and no data
        directives had been used"""
        class R(rend.Page):
            docFactory = loaders.htmlstr('<p nevow:render="foo"></p>')

            def render_foo(self, ctx, data):
                return ctx.tag.clear()[data]

        r = R()
        return deferredRender(r).addCallback(
            lambda result: self.assertIn('None', result))

    test_noData.suppress = [
        SUPPRESS(message=r"\[v0.8\] htmlstr is deprecated because it's buggy. "
                 "Please start using xmlfile and/or xmlstr.")
    ]

    def test_render(self):
        xhtml = '<span nevow:render="replace">replace this</span>'

        class R(rend.Page):
            docFactory = loaders.htmlstr(xhtml)

            def render_replace(self, context, data):
                return context.tag.clear()['abc']

        r = R()
        return deferredRender(r).addCallback(
            lambda result: self.assertEqual(result, '<span>abc</span>'))

    test_render.suppress = [
        SUPPRESS(message=r"\[v0.8\] htmlstr is deprecated because it's buggy. "
                 "Please start using xmlfile and/or xmlstr.")
    ]

    def test_dataAndRender(self):
        xhtml = '''
        <table nevow:data="numbers" nevow:render="sequence">
        <tr nevow:pattern="header"><th>English</th><th>French</th></tr>
        <tr nevow:pattern="item" nevow:render="row"><td><nevow:slot name="english"/></td><td><nevow:slot name="french"/></td></tr>
        </table>
        '''

        class R(rend.Page):
            docFactory = loaders.htmlstr(xhtml)

            def data_numbers(self, context, data):
                return [
                    ['one', 'un/une'],
                    ['two', 'deux'],
                    ['three', 'trois'],
                ]

            def render_row(self, context, data):
                context.fillSlots('english', data[0])
                context.fillSlots('french', data[1])
                return context.tag

        r = R()
        d = deferredRender(r)
        d.addCallback(lambda result: self.assertEqual(
            result, '<table>'
            '<tr><th>English</th><th>French</th></tr>'
            '<tr><td>one</td><td>un/une</td></tr>'
            '<tr><td>two</td><td>deux</td></tr>'
            '<tr><td>three</td><td>trois</td></tr>'
            '</table>'))

    test_dataAndRender.suppress = [
        SUPPRESS(message=r"\[v0.8\] htmlstr is deprecated because it's buggy. "
                 "Please start using xmlfile and/or xmlstr.")
    ]

    def test_stanData(self):
        class R(rend.Page):
            def data_numbers(context, data):
                return ['one', 'two', 'three']

            tags = ul(data=data_numbers, render=directive('sequence'))[li(
                pattern='item')[span(render=str)]]
            docFactory = loaders.stan(tags)

        r = R()
        return deferredRender(r).addCallback(lambda result: self.assertEqual(
            result, '<ul><li>one</li><li>two</li><li>three</li></ul>'))

    def test_stanRender(self):
        class R(rend.Page):
            def render_replace(context, data):
                return context.tag.clear()['abc']

            tags = span(render=render_replace)['replace this']
            docFactory = loaders.stan(tags)

        r = R()
        return deferredRender(r).addCallback(
            lambda result: self.assertEqual(result, '<span>abc</span>'))

    def test_stanDataAndRender(self):
        class R(rend.Page):
            def data_numbers(context, data):
                return [
                    ['one', 'un/une'],
                    ['two', 'deux'],
                    ['three', 'trois'],
                ]

            def render_row(context, data):
                context.fillSlots('english', data[0])
                context.fillSlots('french', data[1])
                return context.tag

            tags = table(data=data_numbers, render=directive('sequence'))[
                tr(pattern='header')[th['English'], th['French']],
                tr(pattern='item', render=render_row)[td[slot('english')],
                                                      td[slot('french')]], ]

            docFactory = loaders.stan(tags)

        r = R()
        return deferredRender(r).addCallback(lambda result: self.assertEqual(
            result,
            '<table><tr><th>English</th><th>French</th></tr><tr><td>one</td><td>un/une</td></tr><tr><td>two</td><td>deux</td></tr><tr><td>three</td><td>trois</td></tr></table>'
        ))

    def test_composite(self):
        class R(rend.Page):
            def render_inner(self, context, data):
                return rend.Page(docFactory=loaders.stan(div(id='inner')))

            docFactory = loaders.stan(
                div(id='outer')[span(render=render_inner)])

        r = R()
        return deferredRender(r).addCallback(lambda result: self.assertEqual(
            result, '<div id="outer"><div id="inner"></div></div>'))

    def _testDocFactoryInStanTree(self, docFactory, expected):
        class Page(rend.Page):
            docFactory = loaders.stan(
                div[invisible(render=directive('included'))])

            def __init__(self, included):
                self.included = included
                rend.Page.__init__(self)

            def render_included(self, context, data):
                return self.included

        return deferredRender(Page(docFactory)).addCallback(
            self.assertEqual, '<div>' + expected + '</div>')

    def test_stanInStanTree(self):
        """
        """
        return self._testDocFactoryInStanTree(loaders.stan(p['fee']),
                                              '<p>fee</p>')

    def test_htmlStringInStanTree(self):
        """
        Test that an htmlstr loader in a stan document is flattened by
        having its document loaded and flattened.
        """
        return self._testDocFactoryInStanTree(loaders.htmlstr('<p>fi</p>'),
                                              '<p>fi</p>')

    test_htmlStringInStanTree.suppress = [
        SUPPRESS(message=r"\[v0.8\] htmlstr is deprecated because it's buggy. "
                 "Please start using xmlfile and/or xmlstr.")
    ]

    def test_xmlStringInStanTree(self):
        """
        Like L{test_htmlStringInStanTree}, but for an xmlstr loader.
        """
        return self._testDocFactoryInStanTree(loaders.xmlstr('<p>fo</p>'),
                                              '<p>fo</p>')

    def test_htmlFileInStanTree(self):
        """
        Like L{test_htmlStringInStanTree}, but for an htmlfile loader.
        """
        doc = '<p>fum</p>'
        temp = self.mktemp()
        f = file(temp, 'w')
        f.write(doc)
        f.close()

        return self._testDocFactoryInStanTree(loaders.htmlfile(temp),
                                              '<p>fum</p>')

    test_htmlFileInStanTree.suppress = [
        SUPPRESS(
            message=r"\[v0.8\] htmlfile is deprecated because it's buggy. "
            "Please start using xmlfile and/or xmlstr.")
    ]

    def test_xmlFileInStanTree(self):
        """
        Like L{test_htmlStringInStanTree}, but for an xmlfile loader.
        """
        doc = '<p>I</p>'
        temp = self.mktemp()
        f = file(temp, 'w')
        f.write(doc)
        f.close()

        return self._testDocFactoryInStanTree(loaders.xmlfile(temp),
                                              '<p>I</p>')

    def test_reusedDocFactory(self):
        """
        Test that a docFactory which is used more than once behaves properly
        both times.
        """
        class Page(rend.Page):
            docFactory = loaders.stan(
                div[invisible(render=directive('included'))])

            def __init__(self, included):
                self.included = included
                rend.Page.__init__(self)

            def render_included(self, context, data):
                return self.included

        p1 = Page(loaders.stan('first'))
        p2 = Page(loaders.xmlstr('<p>second</p>'))

        d = deferredRender(p1)

        def rendered(result):
            self.assertEqual(result, '<div>first</div>')
            return deferredRender(p2)

        d.addCallback(rendered)

        def renderedAgain(result):
            self.assertEqual(result, '<div><p>second</p></div>')

        d.addCallback(renderedAgain)

        return d

    def test_buffered(self):
        class Page(rend.Page):
            buffered = True
            docFactory = loaders.stan(html[head[title['test']]])

        p = Page()
        return deferredRender(p).addCallback(lambda result: self.assertEqual(
            result, '<html><head><title>test</title></head></html>'))

    def test_component(self):
        """
        Test that the data is remembered correctly when a Page is embedded in
        a component-like manner.
        """
        class Data:
            foo = 'foo'
            bar = 'bar'

        class Component(rend.Fragment):
            def render_foo(self, context, data):
                return strong[data.foo]

            def render_bar(self, context, data):
                return data.bar

            docFactory = loaders.stan(p[render_foo, ' ', render_bar])

        class Page(rend.Page):
            docFactory = loaders.stan(div[Component(Data())])

        page = Page()
        return deferredRender(page).addCallback(
            lambda result: self.assertEqual(
                result, '<div><p><strong>foo</strong> bar</p></div>'))

    def test_fragmentContext(self):
        # A fragment is remembered as the IRendererFactory. It must create a new context
        # to avoid messing up the page's context.

        class Fragment(rend.Fragment):
            docFactory = loaders.stan(p(render=directive('foo')))

            def render_foo(self, ctx, data):
                return 'foo'

        class Page(rend.Page):
            docFactory = loaders.stan(
                html(render=directive("template"))[body[
                    p(render=directive("before")), p[slot(name="maincontent")],
                    p(render=directive("after")), ], ])

            def render_before(self, context, data):
                return context.tag["before"]

            def render_template(self, context, data):
                context.fillSlots('maincontent', Fragment())
                return context.tag

            def render_after(self, context, data):
                return context.tag["after"]

        result = Page().renderSynchronously()
        # print result
        self.assertFalse("'foo' was not found" in result)
        self.assertFalse("'after' was not found" in result)

    def test_rendererNotFound(self):
        """
        An unparameterized renderer which is not defined should render a
        message about the renderer not being defined.

        Wanted behaviour: missing renderers etc. raise an exception, with some
        helpful hints on where to locate the typo.

        Feel free to replace test_rendererNotFound{,Parametrized} with unit
        tests for the exception raising behaviour, if you do implement it.
        """
        class Page(rend.Page):
            docFactory = loaders.stan(html(render=directive("notfound")))

        page = Page()
        result = page.renderSynchronously()
        self.assertEqual(
            result,
            "<html>The renderer named 'notfound' was not found in %s.</html>" %
            util.escapeToXML(repr(page)))

    test_rendererNotFound.suppress = [
        SUPPRESS(
            category=DeprecationWarning,
            message=("Renderer 'notfound' missing on nevow.test.test_rend.Page"
                     " will result in an exception."))
    ]

    def test_rendererNotFoundParameterized(self):
        """
        A parameterized renderer which is not defined should render a message
        about the renderer not being defined.
        """
        class Page(rend.Page):
            docFactory = loaders.stan(html(render=directive("notfound dummy")))

        page = Page()
        result = page.renderSynchronously()
        self.assertEqual(
            result,
            "<html>The renderer named 'notfound' was not found in %s.</html>" %
            util.escapeToXML(repr(page)))

    test_rendererNotFoundParameterized.suppress = [
        SUPPRESS(
            category=DeprecationWarning,
            message=("Renderer 'notfound' missing on nevow.test.test_rend.Page"
                     " will result in an exception."))
    ]

    def test_missingRendererDeprecated(self):
        """
        Using a renderer which is not defined should emit a deprecation
        warning.
        """
        rendererName = "notfound"

        class MisdefinedPage(rend.Page):
            docFactory = loaders.stan(html(render=directive(rendererName)))

        page = MisdefinedPage()
        message = "Renderer %r missing on %s will result in an exception."
        message %= (rendererName, qual(MisdefinedPage))
        self.assertWarns(DeprecationWarning, message, rend.__file__,
                         page.renderSynchronously)

    if getattr(unittest.TestCase, 'assertWarns', None) is None:
        test_missingRendererDeprecated.skip = "TestCase.assertWarns missing"

    def test_addSlash(self):
        """
        Accessing a resource that has addSlash set via a path without a
        trailing slash generates a redirect.
        """
        class RootPage(rend.Page):
            def child_child(self, ctx):
                return SlashyPage()

        class SlashyPage(rend.Page):
            addSlash = True
            docFactory = loaders.stan(div(id='inner'))

        root = RootPage()
        r = self.successResultOf(getResource(root, b'/child'))
        r.tag.renderHTTP(r)
        req = inevow.IRequest(r)
        self.assertTrue(req.redirected_to.endswith(b'/'))