# Copyright (c) 2004 Divmod. # See LICENSE for details. from __future__ import generators from twisted.internet import defer from nevow import stan from nevow import context from nevow import tags from nevow import entities from nevow import inevow from nevow import flat from nevow import rend from nevow import compy from nevow.testutil import FakeRequest, TestCase proto = stan.Proto('hello') class Base(TestCase): contextFactory = context.WovenContext def renderer(self, context, data): return lambda context, data: "" def setupContext(self, precompile=False, setupRequest=lambda r:r): fr = setupRequest(FakeRequest()) ctx = context.RequestContext(tag=fr) ctx.remember(fr, inevow.IRequest) ctx.remember(None, inevow.IData) ctx = context.WovenContext(parent=ctx, precompile=precompile) return ctx def render(self, tag, precompile=False, data=None, setupRequest=lambda r: r, setupContext=lambda c:c): ctx = self.setupContext(precompile, setupRequest) ctx = setupContext(ctx) if precompile: return flat.precompile(tag, ctx) else: try: from twisted.trial import util from nevow.flat import twist except ImportError: return flat.flatten(tag, ctx) else: L = [] util.deferredResult(twist.deferflatten(tag, ctx, L.append)) return ''.join(L) class TestSimpleSerialization(Base): def test_serializeProto(self): self.assertEquals(self.render(proto), '') def test_serializeTag(self): tag = proto(someAttribute="someValue") self.assertEquals(self.render(tag), '') def test_serializeChildren(self): tag = proto(someAttribute="someValue")[ proto ] self.assertEquals(self.render(tag), '') def test_serializeWithData(self): tag = proto(data=5) self.assertEquals(self.render(tag), '') def test_adaptRenderer(self): ## This is an implementation of the "adapt" renderer def _(context, data): return context.tag[ data ] tag = proto(data=5, render=_) self.assertEquals(self.render(tag), '5') def test_serializeDataWithRenderer(self): tag = proto(data=5, render=str) self.assertEquals(self.render(tag), '5') def test_noContextRenderer(self): def _(data): return data tag = proto(data=5, render=_) self.assertEquals(self.render(tag), '5') tag = proto(data=5, render=lambda data: data) self.assertEquals(self.render(tag), '5') def test_aBunchOfChildren(self): tag = proto[ "A Child", 5, "A friend in need is a friend indeed" ] self.assertEquals(self.render(tag), 'A Child5A friend in need is a friend indeed') def test_basicPythonTypes(self): tag = proto(data=5)[ "A string; ", u"A unicode string; ", 5, " (An integer) ", 1.0, " (A float) ", 1L, " (A long) ", True, " (A bool) ", ["A ", "List; "], stan.xml(" Some xml; "), lambda data: "A function" ] if self.hasBools: self.assertEquals(self.render(tag), "A string; A unicode string; 5 (An integer) 1.0 (A float) 1 (A long) True (A bool) A List; Some xml; A function") else: self.assertEquals(self.render(tag), "A string; A unicode string; 5 (An integer) 1.0 (A float) 1 (A long) 1 (A bool) A List; Some xml; A function") def test_escaping(self): tag = proto(foo="<>&\"'")["<>&\"'"] self.assertEquals(self.render(tag), '<>&"\'') class TestComplexSerialization(Base): def test_precompileWithRenderer(self): tag = tags.html[ tags.body[ tags.div[ tags.p["Here's a string"], tags.p(data=5, render=str) ] ] ] prelude, context, postlude = self.render(tag, precompile=True) self.assertEquals(prelude, "

Here's a string

") self.assertEquals(context.tag.tagName, "p") self.assertEquals(context.tag.data, 5) self.assertEquals(context.tag.render, str) self.assertEquals(postlude, '
') def test_precompileSlotData(self): """Test that tags with slotData are not precompiled out of the stan tree. """ tag = tags.p[tags.slot('foo')] tag.fillSlots('foo', 'bar') precompiled = self.render(tag, precompile=True) self.assertEquals(self.render(precompiled), '

bar

') def makeComplex(self): return tags.html[ tags.body[ tags.table(data=5)[ tags.tr[ tags.td[ tags.span(render=str) ], ] ] ] ] def test_precompileTwice(self): def render_same(context, data): return context.tag doc = tags.html[ tags.body(render=render_same, data={'foo':5})[ tags.p["Hello"], tags.p(data=tags.directive('foo'))[ str ] ] ] result1 = self.render(doc, precompile=True) result2 = self.render(doc, precompile=True) rendered = self.render(result2) self.assertEquals(rendered, "

Hello

5

") def test_precompilePrecompiled(self): def render_same(context, data): return context.tag doc = tags.html[ tags.body(render=render_same, data={'foo':5})[ tags.p["Hello"], tags.p(data=tags.directive('foo'))[ str ] ] ] result1 = self.render(doc, precompile=True) result2 = self.render(result1, precompile=True) rendered = self.render(result2) self.assertEquals(rendered, "

Hello

5

") def test_precompileDoesntChangeOriginal(self): doc = tags.html(data="foo")[tags.p['foo'], tags.p['foo']] result = self.render(doc, precompile=True) rendered = self.render(result) self.assertEquals(len(doc.children), 2) self.assertEquals(rendered, "

foo

foo

") def test_precompileNestedDynamics(self): tag = self.makeComplex() prelude, dynamic, postlude = self.render(tag, precompile=True) self.assertEquals(prelude, '') self.assertEquals(dynamic.tag.tagName, 'table') self.failUnless(dynamic.tag.children) self.assertEquals(dynamic.tag.data, 5) childPrelude, childDynamic, childPostlude = dynamic.tag.children self.assertEquals(childPrelude, '') self.assertEquals(childDynamic.tag.tagName, 'span') self.assertEquals(childDynamic.tag.render, str) self.assertEquals(childPostlude, '') self.assertEquals(postlude, '') def test_precompileThenRender(self): tag = self.makeComplex() prerendered = self.render(tag, precompile=True) self.assertEquals(self.render(prerendered), '
5
') def test_precompileThenMultipleRenders(self): tag = self.makeComplex() prerendered = self.render(tag, precompile=True) self.assertEquals(self.render(prerendered), '
5
') self.assertEquals(self.render(prerendered), '
5
') def test_patterns(self): tag = tags.html[ tags.body[ tags.ol(data=["one", "two", "three"], render=rend.sequence)[ tags.li(pattern="item")[ str ] ] ] ] self.assertEquals(self.render(tag), "
  1. one
  2. two
  3. three
") def test_precompilePatternWithNoChildren(self): tag = tags.img(pattern='item') pc = flat.precompile(tag) self.assertEquals(pc[0].tag.children, []) def test_slots(self): tag = tags.html[ tags.body[ tags.table(data={'one': 1, 'two': 2}, render=rend.mapping)[ tags.tr[tags.td["Header one."], tags.td["Header two."]], tags.tr[ tags.td["One: ", tags.slot("one")], tags.td["Two: ", tags.slot("two")] ] ] ] ] self.assertEquals(self.render(tag), "
Header one.Header two.
One: 1Two: 2
") def test_slotAttributeEscapingWhenPrecompiled(self): def render_searchResults(ctx, remoteCursor): ctx.fillSlots('old-query', '"meow"') return ctx.tag tag = tags.invisible(render=render_searchResults)[ tags.input(value=tags.slot('old-query')), ] # this test passes if the precompile test is skipped. precompiled = self.render(tag, precompile=True) self.assertEquals(self.render(precompiled), '') test_slotAttributeEscapingWhenPrecompiled.todo = 'this is a bug and should be fixed.' def test_nestedpatterns(self): def data_table(context, data): return [[1,2,3],[4,5,6]] def data_header(context, data): return ['col1', 'col2', 'col3'] tag = tags.html[ tags.body[ tags.table(data=data_table, render=rend.sequence)[ tags.tr(pattern='header', data=data_header, render=rend.sequence)[ tags.td(pattern='item')[str] ], tags.tr(pattern='item', render=rend.sequence)[ tags.td(pattern='item')[str] ] ] ] ] self.assertEquals(self.render(tag), "
col1col2col3
123
456
") def test_cloning(self): def data_foo(context, data): return [{'foo':'one'}, {'foo':'two'}] # tests nested lists without precompilation (precompilation flattens the lists) def render_test(context, data): return tags.ul(render=rend.sequence)[ tags.li(pattern='item')[ 'foo', (((tags.invisible(data=tags.directive('foo'), render=str),),),) ] ] # tests tags inside attributes (weird but useful) document = tags.html(data=data_foo)[ tags.body[ tags.ul(render=rend.sequence)[ tags.li(pattern='item')[ tags.a(href=('test/', tags.invisible(data=tags.directive('foo'), render=str)))['link'] ] ], render_test ] ] document=self.render(document, precompile=True) self.assertEquals(self.render(document), '
  • fooone
  • footwo
') def test_singletons(self): for x in ('img', 'br', 'hr', 'base', 'meta', 'link', 'param', 'area', 'input', 'col', 'basefont', 'isindex', 'frame'): self.assertEquals(self.render(tags.Proto(x)()), '<%s />' % x) def test_nosingleton(self): for x in ('div', 'span', 'script', 'iframe'): self.assertEquals(self.render(tags.Proto(x)()), '<%(tag)s>' % {'tag': x}) def test_nested_data(self): def checkContext(ctx, data): self.assertEquals(data, "inner") self.assertEquals(ctx.locate(inevow.IData, depth=2), "outer") return 'Hi' tag = tags.html(data="outer")[tags.span(render=lambda ctx,data: ctx.tag, data="inner")[checkContext]] self.assertEquals(self.render(tag), "Hi") def test_nested_remember(self): class IFoo(compy.Interface): pass class Foo(str): __implements__ = IFoo def checkContext(ctx, data): self.assertEquals(ctx.locate(IFoo), Foo("inner")) self.assertEquals(ctx.locate(IFoo, depth=2), Foo("outer")) return 'Hi' tag = tags.html(remember=Foo("outer"))[tags.span(render=lambda ctx,data: ctx.tag, remember=Foo("inner"))[checkContext]] self.assertEquals(self.render(tag), "Hi") def test_deferredRememberInRenderer(self): class IFoo(compy.Interface): pass def rememberIt(ctx, data): ctx.remember("bar", IFoo) return defer.succeed(ctx.tag) def locateIt(ctx, data): return IFoo(ctx) tag = tags.invisible(render=rememberIt)[tags.invisible(render=locateIt)] self.assertEquals(self.render(tag), "bar") def test_dataContextCreation(self): data = {'foo':'oof', 'bar':'rab'} doc = tags.p(data=data)[tags.slot('foo'), tags.slot('bar')] doc.fillSlots('foo', tags.invisible(data=tags.directive('foo'), render=str)) doc.fillSlots('bar', lambda ctx,data: data['bar']) self.assertEquals(flat.flatten(doc), '

oofrab

') def test_leaky(self): def foo(ctx, data): ctx.tag.fillSlots('bar', tags.invisible(data="two")) return ctx.tag result = self.render( tags.div(render=foo, data="one")[ tags.slot("bar"), tags.invisible(render=str)]) self.assertEquals(result, '
one
') class TestMultipleRenderWithDirective(Base): def test_it(self): class Cool(object): def __init__(self): self.counter = 0 def count(self, context, data): self.counter += 1 return self.counter it = Cool() tag = tags.html(data={'counter': it.count})[ tags.invisible(data=tags.directive('counter'))[ str ] ] precompiled = self.render(tag, precompile=True) val = self.render(precompiled) self.assertSubstring('1', val) val2 = self.render(precompiled) self.assertSubstring('2', val2) class TestEntity(Base): def test_it(self): val = self.render(entities.nbsp) self.assertEquals(val, ' ') def test_nested(self): val = self.render(tags.html(src=entities.quot)[entities.amp]) self.assertEquals(val, '&') def test_xml(self): val = self.render([entities.lt, entities.amp, entities.gt]) self.assertEquals(val, '<&>') class TestNoneAttribute(Base): def test_simple(self): val = self.render(tags.html(foo=None)["Bar"]) self.assertEquals(val, "Bar") def test_slot(self): val = self.render(tags.html().fillSlots('bar', None)(foo=tags.slot('bar'))["Bar"]) self.assertEquals(val, "Bar") test_slot.todo = "We need to be able to roll back time in order to not output the attribute name" class TestKey(Base): def test_nested(self): val = [] def appendKey(ctx, data): val.append(ctx.key) return ctx.tag self.render( tags.div(key="one", render=appendKey)[ tags.div(key="two", render=appendKey)[ tags.div(render=appendKey)[ tags.div(key="four", render=appendKey)]]]) self.assertEquals(val, ["one", "one.two", "one.two", "one.two.four"])