A fork of hyde, the static site generation. Some patches will be pushed upstream.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

431 lines
10 KiB

  1. # -*- coding: utf-8 -*-
  2. """
  3. Use nose
  4. `$ pip install nose`
  5. `$ nosetests`
  6. Code borrowed from rwbench.py from the jinja2 examples
  7. """
  8. from datetime import datetime
  9. from hyde.ext.templates.jinja import Jinja2Template
  10. from hyde.fs import File, Folder
  11. from hyde.site import Site
  12. from hyde.generator import Generator
  13. from hyde.model import Config
  14. import jinja2
  15. from jinja2.utils import generate_lorem_ipsum
  16. from random import choice, randrange
  17. from util import assert_html_equals
  18. import yaml
  19. from pyquery import PyQuery
  20. from nose.tools import raises, nottest, with_setup
  21. ROOT = File(__file__).parent
  22. JINJA2 = ROOT.child_folder('templates/jinja2')
  23. class Article(object):
  24. def __init__(self, id):
  25. self.id = id
  26. self.href = '/article/%d' % self.id
  27. self.title = generate_lorem_ipsum(1, False, 5, 10)
  28. self.user = choice(users)
  29. self.body = generate_lorem_ipsum()
  30. self.pub_date = datetime.utcfromtimestamp(randrange(10 ** 9, 2 * 10 ** 9))
  31. self.published = True
  32. def dateformat(x):
  33. return x.strftime('%Y-%m-%d')
  34. class User(object):
  35. def __init__(self, username):
  36. self.href = '/user/%s' % username
  37. self.username = username
  38. users = map(User, [u'John Doe', u'Jane Doe', u'Peter Somewhat'])
  39. articles = map(Article, range(20))
  40. navigation = [
  41. ('index', 'Index'),
  42. ('about', 'About'),
  43. ('foo?bar=1', 'Foo with Bar'),
  44. ('foo?bar=2&s=x', 'Foo with X'),
  45. ('blah', 'Blub Blah'),
  46. ('hehe', 'Haha'),
  47. ] * 5
  48. context = dict(users=users, articles=articles, page_navigation=navigation)
  49. def test_render():
  50. """
  51. Uses pyquery to test the html structure for validity
  52. """
  53. t = Jinja2Template(JINJA2.path)
  54. t.configure(None)
  55. t.env.filters['dateformat'] = dateformat
  56. source = File(JINJA2.child('index.html')).read_all()
  57. html = t.render(source, context)
  58. actual = PyQuery(html)
  59. assert actual(".navigation li").length == 30
  60. assert actual("div.article").length == 20
  61. assert actual("div.article h2").length == 20
  62. assert actual("div.article h2 a").length == 20
  63. assert actual("div.article p.meta").length == 20
  64. assert actual("div.article div.text").length == 20
  65. def test_typogrify():
  66. source = """
  67. {%filter typogrify%}
  68. One & two
  69. {%endfilter%}
  70. """
  71. t = Jinja2Template(JINJA2.path)
  72. t.configure(None)
  73. html = t.render(source, {}).strip()
  74. assert html == u'One <span class="amp">&amp;</span>&nbsp;two'
  75. def test_markdown():
  76. source = """
  77. {%markdown%}
  78. ### Heading 3
  79. {%endmarkdown%}
  80. """
  81. t = Jinja2Template(JINJA2.path)
  82. t.configure(None)
  83. html = t.render(source, {}).strip()
  84. assert html == u'<h3>Heading 3</h3>'
  85. def test_markdown_with_extensions():
  86. source = """
  87. {%markdown%}
  88. ### Heading 3
  89. {%endmarkdown%}
  90. """
  91. t = Jinja2Template(JINJA2.path)
  92. s = Site(JINJA2.path)
  93. c = Config(JINJA2.path, config_dict=dict(markdown=dict(extensions=['headerid'])))
  94. s.config = c
  95. t.configure(s)
  96. html = t.render(source, {}).strip()
  97. assert html == u'<h3 id="heading_3">Heading 3</h3>'
  98. TEST_SITE = File(__file__).parent.child_folder('_test')
  99. @nottest
  100. def assert_markdown_typogrify_processed_well(include_text, includer_text):
  101. site = Site(TEST_SITE)
  102. site.config.plugins = ['hyde.ext.plugins.meta.MetaPlugin']
  103. inc = File(TEST_SITE.child('content/inc.md'))
  104. inc.write(include_text)
  105. site.load()
  106. gen = Generator(site)
  107. gen.load_template_if_needed()
  108. template = gen.template
  109. html = template.render(includer_text, {}).strip()
  110. print html
  111. assert html
  112. q = PyQuery(html)
  113. assert "is_processable" not in html
  114. assert "This is a" in q("h1").text()
  115. assert "heading" in q("h1").text()
  116. assert q(".amp").length == 1
  117. return html
  118. class TestJinjaTemplate(object):
  119. def setUp(self):
  120. TEST_SITE.make()
  121. TEST_SITE.parent.child_folder('sites/test_jinja').copy_contents_to(TEST_SITE)
  122. def tearDown(self):
  123. TEST_SITE.delete()
  124. def test_depends(self):
  125. t = Jinja2Template(JINJA2.path)
  126. t.configure(None)
  127. deps = list(t.get_dependencies('index.html'))
  128. assert len(deps) == 2
  129. assert 'helpers.html' in deps
  130. assert 'layout.html' in deps
  131. def test_depends_multi_level(self):
  132. site = Site(TEST_SITE)
  133. JINJA2.copy_contents_to(site.content.source)
  134. inc = File(TEST_SITE.child('content/inc.md'))
  135. inc.write("{% extends 'index.html' %}")
  136. site.load()
  137. gen = Generator(site)
  138. gen.load_template_if_needed()
  139. t = gen.template
  140. deps = list(t.get_dependencies('inc.md'))
  141. assert len(deps) == 3
  142. assert 'helpers.html' in deps
  143. assert 'layout.html' in deps
  144. assert 'index.html' in deps
  145. def test_depends_with_reference_tag(self):
  146. site = Site(TEST_SITE)
  147. JINJA2.copy_contents_to(site.content.source)
  148. inc = File(TEST_SITE.child('content/inc.md'))
  149. inc.write("{% refer to 'index.html' as index%}")
  150. site.load()
  151. gen = Generator(site)
  152. gen.load_template_if_needed()
  153. t = gen.template
  154. deps = list(t.get_dependencies('inc.md'))
  155. assert len(deps) == 3
  156. assert 'helpers.html' in deps
  157. assert 'layout.html' in deps
  158. assert 'index.html' in deps
  159. def test_cant_find_depends_with_reference_tag_var(self):
  160. site = Site(TEST_SITE)
  161. JINJA2.copy_contents_to(site.content.source)
  162. inc = File(TEST_SITE.child('content/inc.md'))
  163. inc.write("{% set ind = 'index.html' %}{% refer to ind as index %}")
  164. site.load()
  165. gen = Generator(site)
  166. gen.load_template_if_needed()
  167. t = gen.template
  168. deps = list(t.get_dependencies('inc.md'))
  169. assert len(deps) == 1
  170. assert not deps[0]
  171. def test_can_include_templates_with_processing(self):
  172. text = """
  173. ===
  174. is_processable: False
  175. ===
  176. {% filter typogrify %}{% markdown %}
  177. This is a heading
  178. =================
  179. Hyde & Jinja.
  180. {% endmarkdown %}{% endfilter %}
  181. """
  182. text2 = """{% include "inc.md" %}"""
  183. assert_markdown_typogrify_processed_well(text, text2)
  184. def test_includetext(self):
  185. text = """
  186. ===
  187. is_processable: False
  188. ===
  189. This is a heading
  190. =================
  191. Hyde & Jinja.
  192. """
  193. text2 = """{% includetext "inc.md" %}"""
  194. assert_markdown_typogrify_processed_well(text, text2)
  195. def test_reference_is_noop(self):
  196. text = """
  197. ===
  198. is_processable: False
  199. ===
  200. {% mark heading %}
  201. This is a heading
  202. =================
  203. {% endmark %}
  204. {% reference content %}
  205. Hyde & Jinja.
  206. {% endreference %}
  207. """
  208. text2 = """{% includetext "inc.md" %}"""
  209. html = assert_markdown_typogrify_processed_well(text, text2)
  210. assert "mark" not in html
  211. assert "reference" not in html
  212. def test_refer(self):
  213. text = """
  214. ===
  215. is_processable: False
  216. ===
  217. {% filter markdown|typogrify %}
  218. {% mark heading %}
  219. This is a heading
  220. =================
  221. {% endmark %}
  222. {% reference content %}
  223. Hyde & Jinja.
  224. {% endreference %}
  225. {% endfilter %}
  226. """
  227. text2 = """
  228. {% refer to "inc.md" as inc %}
  229. {% filter markdown|typogrify %}
  230. {{ inc.heading }}
  231. {{ inc.content }}
  232. {% endfilter %}
  233. """
  234. html = assert_markdown_typogrify_processed_well(text, text2)
  235. assert "mark" not in html
  236. assert "reference" not in html
  237. def test_refer_with_full_html(self):
  238. text = """
  239. ===
  240. is_processable: False
  241. ===
  242. <div class="fulltext">
  243. {% filter markdown|typogrify %}
  244. {% mark heading %}
  245. This is a heading
  246. =================
  247. {% endmark %}
  248. {% reference content %}
  249. Hyde & Jinja.
  250. {% endreference %}
  251. {% endfilter %}
  252. </div>
  253. """
  254. text2 = """
  255. {% refer to "inc.md" as inc %}
  256. {{ inc.html('.fulltext') }}
  257. """
  258. html = assert_markdown_typogrify_processed_well(text, text2)
  259. assert "mark" not in html
  260. assert "reference" not in html
  261. def test_two_level_refer_with_var(self):
  262. text = """
  263. ===
  264. is_processable: False
  265. ===
  266. <div class="fulltext">
  267. {% filter markdown|typogrify %}
  268. {% mark heading %}
  269. This is a heading
  270. =================
  271. {% endmark %}
  272. {% reference content %}
  273. Hyde & Jinja.
  274. {% endreference %}
  275. {% endfilter %}
  276. </div>
  277. """
  278. text2 = """
  279. {% set super = 'super.md' %}
  280. {% refer to super as sup %}
  281. <div class="justhead">
  282. {% mark child %}
  283. {{ sup.heading }}
  284. {% endmark %}
  285. {% mark cont %}
  286. {{ sup.content }}
  287. {% endmark %}
  288. </div>
  289. """
  290. text3 = """
  291. {% set incu = 'inc.md' %}
  292. {% refer to incu as inc %}
  293. {% filter markdown|typogrify %}
  294. {{ inc.child }}
  295. {{ inc.cont }}
  296. {% endfilter %}
  297. """
  298. superinc = File(TEST_SITE.child('content/super.md'))
  299. superinc.write(text)
  300. html = assert_markdown_typogrify_processed_well(text2, text3)
  301. assert "mark" not in html
  302. assert "reference" not in html
  303. def test_refer_with_var(self):
  304. text = """
  305. ===
  306. is_processable: False
  307. ===
  308. <div class="fulltext">
  309. {% filter markdown|typogrify %}
  310. {% mark heading %}
  311. This is a heading
  312. =================
  313. {% endmark %}
  314. {% reference content %}
  315. Hyde & Jinja.
  316. {% endreference %}
  317. {% endfilter %}
  318. </div>
  319. """
  320. text2 = """
  321. {% set incu = 'inc.md' %}
  322. {% refer to incu as inc %}
  323. {{ inc.html('.fulltext') }}
  324. """
  325. html = assert_markdown_typogrify_processed_well(text, text2)
  326. assert "mark" not in html
  327. assert "reference" not in html
  328. def test_yaml_tag(salf):
  329. text = """
  330. {% yaml test %}
  331. one:
  332. - A
  333. - B
  334. - C
  335. two:
  336. - D
  337. - E
  338. - F
  339. {% endyaml %}
  340. {% for section, values in test.items() %}
  341. <ul class="{{ section }}">
  342. {% for value in values %}
  343. <li>{{ value }}</li>
  344. {% endfor %}
  345. </ul>
  346. {% endfor %}
  347. """
  348. t = Jinja2Template(JINJA2.path)
  349. t.configure(None)
  350. html = t.render(text, {}).strip()
  351. actual = PyQuery(html)
  352. assert actual("ul").length == 2
  353. assert actual("ul.one").length == 1
  354. assert actual("ul.two").length == 1
  355. assert actual("li").length == 6
  356. assert actual("ul.one li").length == 3
  357. assert actual("ul.two li").length == 3
  358. ones = [item.text for item in actual("ul.one li")]
  359. assert ones == ["A", "B", "C"]
  360. twos = [item.text for item in actual("ul.two li")]
  361. assert twos == ["D", "E", "F"]