PageRenderTime 38ms CodeModel.GetById 43ms RepoModel.GetById 0ms app.codeStats 0ms

/plone/app/blocks/tests/test_tiles.py

https://github.com/plone/plone.app.blocks
Python | 283 lines | 273 code | 8 blank | 2 comment | 8 complexity | 2f752ecb68f0323e12e92597db7a2a4c MD5 | raw file
  1. from plone.app.blocks.testing import BLOCKS_FIXTURE
  2. from plone.app.blocks.tiles import renderTiles
  3. from plone.app.testing import IntegrationTesting
  4. from plone.app.testing import PloneSandboxLayer
  5. from plone.tiles import Tile
  6. from repoze.xmliter.utils import getHTMLSerializer
  7. from zope import schema
  8. from zope.configuration import xmlconfig
  9. from zope.interface import implementer
  10. from zope.interface import Interface
  11. import unittest
  12. try:
  13. # Python 2: "unicode" is built-in
  14. unicode
  15. except NameError:
  16. unicode = str
  17. class ITestTile(Interface):
  18. magicNumber = schema.Int(title="Magic number", required=False)
  19. @implementer(ITestTile)
  20. class TestTile(Tile):
  21. def __call__(self):
  22. # fake a page template to keep things simple in the test
  23. return """\
  24. <html>
  25. <head>
  26. <meta name="tile-name" content="%(name)s" />
  27. </head>
  28. <body>
  29. <p>
  30. This is a demo tile with id %(name)s
  31. </p>
  32. <p>
  33. Magic number: %(number)d; Form: %(form)s;
  34. Query string: %(queryString)s; URL: %(url)s
  35. Umlauts: Übertile ;)
  36. </p>
  37. </body>
  38. </html>""" % dict(
  39. name=self.id,
  40. number=self.data["magicNumber"] or -1,
  41. form=sorted(self.request.form.items()),
  42. queryString=self.request["QUERY_STRING"],
  43. url=self.request.getURL(),
  44. )
  45. class TestTile2(Tile):
  46. def __call__(self):
  47. return """\
  48. <html>
  49. <body>
  50. <p>
  51. I'm a tile calling another tile as subtile.
  52. </p>
  53. <div data-tile="./@@test.tile1/subtile"/>
  54. </body>
  55. </html>"""
  56. class TestTile3(Tile):
  57. def __call__(self):
  58. return """\
  59. <title>structureless in %s</title>
  60. """ % self.request.form.get(
  61. "title", ""
  62. )
  63. @implementer(ITestTile)
  64. class TestTileBroken(Tile):
  65. def __call__(self):
  66. raise Exception("This tile is broken.")
  67. class TestTilesLayer(PloneSandboxLayer):
  68. defaultBases = (BLOCKS_FIXTURE,)
  69. def setUpZope(self, app, configurationContext):
  70. xmlconfig.string(
  71. """\
  72. <configure
  73. xmlns="http://namespaces.zope.org/zope"
  74. xmlns:plone="http://namespaces.plone.org/plone"
  75. i18n_domain="plone.app.blocks">
  76. <include package="plone.tiles" file="meta.zcml" />
  77. <plone:tile
  78. name="test.tile1"
  79. title="Test Tile"
  80. description=""
  81. add_permission="cmf.ModifyPortalContent"
  82. schema="plone.app.blocks.tests.test_tiles.ITestTile"
  83. class="plone.app.blocks.tests.test_tiles.TestTile"
  84. permission="zope2.View"
  85. for="*"
  86. />
  87. <plone:tile
  88. name="test.tile2"
  89. title="Test Tile 2"
  90. description="Tile calling tile1 as subtile"
  91. add_permission="cmf.ModifyPortalContent"
  92. class="plone.app.blocks.tests.test_tiles.TestTile2"
  93. permission="zope2.View"
  94. for="*"
  95. />
  96. <plone:tile
  97. name="test.tile3"
  98. title="Test Tile 3"
  99. add_permission="cmf.ModifyPortalContent"
  100. class="plone.app.blocks.tests.test_tiles.TestTile3"
  101. permission="zope2.View"
  102. for="*"
  103. />
  104. <plone:tile
  105. name="test.tile1.broken"
  106. title="Broken Test Tile"
  107. description=""
  108. add_permission="cmf.ModifyPortalContent"
  109. schema="plone.app.blocks.tests.test_tiles.ITestTile"
  110. class="plone.app.blocks.tests.test_tiles.TestTileBroken"
  111. permission="zope2.View"
  112. for="*"
  113. />
  114. </configure>
  115. """,
  116. context=configurationContext,
  117. )
  118. BLOCKS_TILES_FIXTURE = TestTilesLayer()
  119. BLOCKS_TILES_INTEGRATION_TESTING = IntegrationTesting(
  120. bases=(BLOCKS_TILES_FIXTURE,), name="Blocks:Tiles:Integration"
  121. )
  122. testLayout1 = """\
  123. <!DOCTYPE html>
  124. <html data-layout="./@@default-site-layout">
  125. <head></head>
  126. <body>
  127. <h1>Welcome!</h1>
  128. <div data-panel="panel1">
  129. Page panel 1
  130. <div id="page-tile2" data-tile="./@@test.tile1/tile2?magicNumber:int=2">Page tile 2 placeholder</div>
  131. </div>
  132. <div data-panel="panel2">
  133. Page panel 2
  134. <div id="page-tile3" data-tile="./@@test.tile1/tile3">Page tile 3 placeholder</div>
  135. </div>
  136. <div data-panel="panel4">
  137. Page panel 4 (ignored)
  138. <div id="page-tile4" data-tile="./@@test.tile1/tile4">Page tile 4 placeholder</div>
  139. </div>
  140. </body>
  141. </html>
  142. """ # noqa
  143. testLayout2 = """\
  144. <!DOCTYPE html>
  145. <html data-layout="./@@default-site-layout">
  146. <head></head>
  147. <body>
  148. <h1>Welcome!</h1>
  149. <div data-panel="panel1">
  150. Page panel 1
  151. <div id="page-tile2" data-tile="./@@test.tile1/tile2?magicNumber:int=2">Page tile 2 placeholder</div>
  152. </div>
  153. <div data-panel="panel2">
  154. Page panel 2
  155. <div id="page-tile3" data-tile="./@@test.tile1.broken/tile3">Page tile 3 placeholder</div>
  156. </div>
  157. <div data-panel="panel4">
  158. Page panel 4 (ignored)
  159. <div id="page-tile4" data-tile="./@@test.tile1/tile4">Page tile 4 placeholder</div>
  160. </div>
  161. </body>
  162. </html>
  163. """ # noqa
  164. testLayout3 = """\
  165. <!DOCTYPE html>
  166. <html>
  167. <head>
  168. <div data-tile="./@@test.tile3?title=head"/>
  169. </head>
  170. <body>
  171. <h1>Welcome!</h1>
  172. <div data-panel="panel1">
  173. <div data-tile="./@@test.tile2"/>
  174. </div>
  175. <div data-tile="./@@test.tile3?title=body"/>
  176. </body>
  177. </html>
  178. """
  179. testLayout4 = """\
  180. <!DOCTYPE html>
  181. <html>
  182. <head>
  183. <div data-tile="./@@test.tile1.broken"/>
  184. <div data-tile="./@@tiledoesnotexist"/>
  185. </head>
  186. <body>
  187. <h1>hi there!</h1>
  188. <div data-tile="./@@tiledoesnotexist"/>
  189. </body>
  190. </html>
  191. """
  192. class TestRenderTiles(unittest.TestCase):
  193. layer = BLOCKS_TILES_INTEGRATION_TESTING
  194. def testRenderTiles(self):
  195. serializer = getHTMLSerializer([testLayout1])
  196. request = self.layer["request"]
  197. tree = serializer.tree
  198. renderTiles(request, tree)
  199. result = unicode(serializer)
  200. self.assertIn("This is a demo tile with id tile2", result)
  201. self.assertIn("This is a demo tile with id tile3", result)
  202. self.assertIn("This is a demo tile with id tile4", result)
  203. self.assertIn("Umlauts: \xdcbertile", result)
  204. def testRenderTilesError(self):
  205. serializer = getHTMLSerializer([testLayout2])
  206. request = self.layer["request"]
  207. tree = serializer.tree
  208. renderTiles(request, tree)
  209. result = str(serializer)
  210. self.assertIn("This is a demo tile with id tile2", result)
  211. self.assertNotIn("This is a demo tile with id tile3", result)
  212. self.assertIn("There was an error", result)
  213. self.assertIn("This is a demo tile with id tile4", result)
  214. def testRenderSubTiles(self):
  215. """Test if subtiles - tiles referenced in tiles - are resolved."""
  216. serializer = getHTMLSerializer([testLayout3])
  217. request = self.layer["request"]
  218. tree = serializer.tree
  219. renderTiles(request, tree)
  220. result = str(serializer)
  221. self.assertIn("I'm a tile calling another tile as subtile.", result)
  222. self.assertIn("This is a demo tile with id subtile", result)
  223. def testRenderStructurelessTiles(self):
  224. """Test if tiles without a html/head/body structure are also rendered."""
  225. serializer = getHTMLSerializer([testLayout3])
  226. request = self.layer["request"]
  227. tree = serializer.tree
  228. renderTiles(request, tree)
  229. result = str(serializer)
  230. self.assertIn("structureless in head", result)
  231. self.assertIn("structureless in body", result)
  232. def testNonExistentAndBrokenTiiles(self):
  233. """Test if non-existent or broken tiles do not end in an recursive loop."""
  234. serializer = getHTMLSerializer([testLayout4])
  235. request = self.layer["request"]
  236. tree = serializer.tree
  237. renderTiles(request, tree)
  238. result = str(serializer)
  239. self.assertIn("hi there!", result)