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.
 
 
 

372 lines
16 KiB

  1. # -*- coding: utf-8 -*-
  2. """
  3. Use nose
  4. `$ pip install nose`
  5. `$ nosetests`
  6. """
  7. from hyde.exceptions import HydeException
  8. from hyde.fs import File, Folder
  9. from hyde.generator import Generator
  10. from hyde.plugin import Plugin
  11. from hyde.site import Site
  12. from hyde.model import Expando
  13. from mock import patch, Mock
  14. from nose.tools import raises, nottest, with_setup
  15. TEST_SITE = File(__file__).parent.child_folder('_test')
  16. class PluginLoaderStub(Plugin):
  17. pass
  18. class NoReturnPlugin(Plugin):
  19. def begin_text_resource(self, resource, text):
  20. print "NoReturnPlugin"
  21. return None
  22. class ConstantReturnPlugin(Plugin):
  23. def begin_text_resource(self, resource, text):
  24. print "ConstantReturnPlugin"
  25. return "Jam"
  26. class TestPlugins(object):
  27. @classmethod
  28. def setup_class(cls):
  29. TEST_SITE.make()
  30. TEST_SITE.parent.child_folder('sites/test_jinja').copy_contents_to(TEST_SITE)
  31. folders = []
  32. text_files = []
  33. binary_files = []
  34. with TEST_SITE.child_folder('content').walker as walker:
  35. @walker.folder_visitor
  36. def visit_folder(folder):
  37. folders.append(folder.path)
  38. @walker.file_visitor
  39. def visit_file(afile):
  40. if not afile.is_text:
  41. binary_files.append(afile.path)
  42. else:
  43. text_files.append(afile.path)
  44. cls.content_nodes = sorted(folders)
  45. cls.content_text_resources = sorted(text_files)
  46. cls.content_binary_resources = sorted(binary_files)
  47. @classmethod
  48. def teardown_class(cls):
  49. TEST_SITE.delete()
  50. def setUp(self):
  51. self.site = Site(TEST_SITE)
  52. self.site.config.plugins = ['hyde.tests.test_plugin.PluginLoaderStub']
  53. def test_can_load_plugin_modules(self):
  54. assert not len(self.site.plugins)
  55. Plugin.load_all(self.site)
  56. assert len(self.site.plugins) == 1
  57. assert self.site.plugins[0].__class__.__name__ == 'PluginLoaderStub'
  58. def test_generator_loads_plugins(self):
  59. gen = Generator(self.site)
  60. assert len(self.site.plugins) == 1
  61. def test_generator_template_registered_called(self):
  62. with patch.object(PluginLoaderStub, 'template_loaded') as template_loaded_stub:
  63. gen = Generator(self.site)
  64. gen.generate_all()
  65. assert template_loaded_stub.call_count == 1
  66. def test_generator_template_begin_generation_called(self):
  67. with patch.object(PluginLoaderStub, 'begin_generation') as begin_generation_stub:
  68. gen = Generator(self.site)
  69. gen.generate_all()
  70. assert begin_generation_stub.call_count == 1
  71. def test_generator_template_begin_generation_called_for_single_resource(self):
  72. with patch.object(PluginLoaderStub, 'begin_generation') as begin_generation_stub:
  73. gen = Generator(self.site)
  74. path = self.site.content.source_folder.child('about.html')
  75. gen.generate_resource_at_path(path)
  76. assert begin_generation_stub.call_count == 1
  77. def test_generator_template_begin_generation_called_for_single_node(self):
  78. with patch.object(PluginLoaderStub, 'begin_generation') as begin_generation_stub:
  79. gen = Generator(self.site)
  80. path = self.site.content.source_folder
  81. gen.generate_node_at_path(path)
  82. assert begin_generation_stub.call_count == 1
  83. def test_generator_template_generation_complete_called(self):
  84. with patch.object(PluginLoaderStub, 'generation_complete') as generation_complete_stub:
  85. gen = Generator(self.site)
  86. gen.generate_all()
  87. assert generation_complete_stub.call_count == 1
  88. def test_generator_template_generation_complete_called_for_single_resource(self):
  89. with patch.object(PluginLoaderStub, 'generation_complete') as generation_complete_stub:
  90. gen = Generator(self.site)
  91. path = self.site.content.source_folder.child('about.html')
  92. gen.generate_resource_at_path(path)
  93. assert generation_complete_stub.call_count == 1
  94. def test_generator_template_generation_complete_called_for_single_node(self):
  95. with patch.object(PluginLoaderStub, 'generation_complete') as generation_complete_stub:
  96. gen = Generator(self.site)
  97. path = self.site.content.source_folder
  98. gen.generate_node_at_path(path)
  99. assert generation_complete_stub.call_count == 1
  100. def test_generator_template_begin_site_called(self):
  101. with patch.object(PluginLoaderStub, 'begin_site') as begin_site_stub:
  102. gen = Generator(self.site)
  103. gen.generate_all()
  104. assert begin_site_stub.call_count == 1
  105. def test_generator_template_begin_site_called_for_single_resource(self):
  106. with patch.object(PluginLoaderStub, 'begin_site') as begin_site_stub:
  107. gen = Generator(self.site)
  108. path = self.site.content.source_folder.child('about.html')
  109. gen.generate_resource_at_path(path)
  110. assert begin_site_stub.call_count == 1
  111. def test_generator_template_begin_site_not_called_for_single_resource_second_time(self):
  112. with patch.object(PluginLoaderStub, 'begin_site') as begin_site_stub:
  113. gen = Generator(self.site)
  114. gen.generate_all()
  115. assert begin_site_stub.call_count == 1
  116. path = self.site.content.source_folder.child('about.html')
  117. gen.generate_resource_at_path(path)
  118. assert begin_site_stub.call_count == 1
  119. def test_generator_template_begin_site_called_for_single_node(self):
  120. with patch.object(PluginLoaderStub, 'begin_site') as begin_site_stub:
  121. gen = Generator(self.site)
  122. path = self.site.content.source_folder
  123. gen.generate_node_at_path(path)
  124. assert begin_site_stub.call_count == 1
  125. def test_generator_template_begin_site_not_called_for_single_node_second_time(self):
  126. with patch.object(PluginLoaderStub, 'begin_site') as begin_site_stub:
  127. gen = Generator(self.site)
  128. gen.generate_all()
  129. assert begin_site_stub.call_count == 1
  130. path = self.site.content.source_folder
  131. gen.generate_node_at_path(path)
  132. assert begin_site_stub.call_count == 1
  133. def test_generator_template_site_complete_called(self):
  134. with patch.object(PluginLoaderStub, 'site_complete') as site_complete_stub:
  135. gen = Generator(self.site)
  136. gen.generate_all()
  137. assert site_complete_stub.call_count == 1
  138. def test_generator_template_site_complete_called_for_single_resource(self):
  139. with patch.object(PluginLoaderStub, 'site_complete') as site_complete_stub:
  140. gen = Generator(self.site)
  141. path = self.site.content.source_folder.child('about.html')
  142. gen.generate_resource_at_path(path)
  143. assert site_complete_stub.call_count == 1
  144. def test_generator_template_site_complete_not_called_for_single_resource_second_time(self):
  145. with patch.object(PluginLoaderStub, 'site_complete') as site_complete_stub:
  146. gen = Generator(self.site)
  147. gen.generate_all()
  148. assert site_complete_stub.call_count == 1
  149. path = self.site.content.source_folder.child('about.html')
  150. gen.generate_resource_at_path(path)
  151. assert site_complete_stub.call_count == 1
  152. def test_generator_template_site_complete_called_for_single_node(self):
  153. with patch.object(PluginLoaderStub, 'site_complete') as site_complete_stub:
  154. gen = Generator(self.site)
  155. path = self.site.content.source_folder
  156. gen.generate_node_at_path(path)
  157. assert site_complete_stub.call_count == 1
  158. def test_generator_template_site_complete_not_called_for_single_node_second_time(self):
  159. with patch.object(PluginLoaderStub, 'site_complete') as site_complete_stub:
  160. gen = Generator(self.site)
  161. gen.generate_all()
  162. path = self.site.content.source_folder
  163. gen.generate_node_at_path(path)
  164. assert site_complete_stub.call_count == 1
  165. def test_generator_template_begin_node_called(self):
  166. with patch.object(PluginLoaderStub, 'begin_node') as begin_node_stub:
  167. gen = Generator(self.site)
  168. gen.generate_all()
  169. assert begin_node_stub.call_count == len(self.content_nodes)
  170. called_with_nodes = sorted([arg[0][0].path for arg in begin_node_stub.call_args_list])
  171. assert called_with_nodes == self.content_nodes
  172. def test_generator_template_begin_node_called_for_single_resource(self):
  173. with patch.object(PluginLoaderStub, 'begin_node') as begin_node_stub:
  174. gen = Generator(self.site)
  175. gen.generate_resource_at_path(self.site.content.source_folder.child('about.html'))
  176. assert begin_node_stub.call_count == len(self.content_nodes)
  177. def test_generator_template_begin_node_not_called_for_single_resource_second_time(self):
  178. with patch.object(PluginLoaderStub, 'begin_node') as begin_node_stub:
  179. gen = Generator(self.site)
  180. gen.generate_all()
  181. assert begin_node_stub.call_count == len(self.content_nodes)
  182. gen.generate_resource_at_path(self.site.content.source_folder.child('about.html'))
  183. assert begin_node_stub.call_count == len(self.content_nodes) # No extra calls
  184. def test_generator_template_node_complete_called(self):
  185. with patch.object(PluginLoaderStub, 'node_complete') as node_complete_stub:
  186. gen = Generator(self.site)
  187. gen.generate_all()
  188. assert node_complete_stub.call_count == len(self.content_nodes)
  189. called_with_nodes = sorted([arg[0][0].path for arg in node_complete_stub.call_args_list])
  190. assert called_with_nodes == self.content_nodes
  191. def test_generator_template_node_complete_called_for_single_resource(self):
  192. with patch.object(PluginLoaderStub, 'node_complete') as node_complete_stub:
  193. gen = Generator(self.site)
  194. gen.generate_resource_at_path(self.site.content.source_folder.child('about.html'))
  195. assert node_complete_stub.call_count == len(self.content_nodes)
  196. def test_generator_template_node_complete_not_called_for_single_resource_second_time(self):
  197. with patch.object(PluginLoaderStub, 'node_complete') as node_complete_stub:
  198. gen = Generator(self.site)
  199. gen.generate_all()
  200. assert node_complete_stub.call_count == len(self.content_nodes)
  201. gen.generate_resource_at_path(self.site.content.source_folder.child('about.html'))
  202. assert node_complete_stub.call_count == len(self.content_nodes) # No extra calls
  203. def test_generator_template_begin_text_resource_called(self):
  204. with patch.object(PluginLoaderStub, 'begin_text_resource') as begin_text_resource_stub:
  205. begin_text_resource_stub.reset_mock()
  206. begin_text_resource_stub.return_value = ''
  207. gen = Generator(self.site)
  208. gen.generate_all()
  209. called_with_resources = sorted([arg[0][0].path for arg in begin_text_resource_stub.call_args_list])
  210. assert set(called_with_resources) == set(self.content_text_resources)
  211. def test_generator_template_begin_text_resource_called_for_single_resource(self):
  212. with patch.object(PluginLoaderStub, 'begin_text_resource') as begin_text_resource_stub:
  213. begin_text_resource_stub.return_value = ''
  214. gen = Generator(self.site)
  215. gen.generate_all()
  216. begin_text_resource_stub.reset_mock()
  217. path = self.site.content.source_folder.child('about.html')
  218. gen = Generator(self.site)
  219. gen.generate_resource_at_path(path, incremental=True)
  220. called_with_resources = sorted([arg[0][0].path for arg in begin_text_resource_stub.call_args_list])
  221. assert begin_text_resource_stub.call_count == 1
  222. assert called_with_resources[0] == path
  223. def test_generator_template_begin_binary_resource_called(self):
  224. with patch.object(PluginLoaderStub, 'begin_binary_resource') as begin_binary_resource_stub:
  225. gen = Generator(self.site)
  226. gen.generate_all()
  227. called_with_resources = sorted([arg[0][0].path for arg in begin_binary_resource_stub.call_args_list])
  228. assert begin_binary_resource_stub.call_count == len(self.content_binary_resources)
  229. assert called_with_resources == self.content_binary_resources
  230. def test_generator_template_begin_binary_resource_called_for_single_resource(self):
  231. with patch.object(PluginLoaderStub, 'begin_binary_resource') as begin_binary_resource_stub:
  232. gen = Generator(self.site)
  233. gen.generate_all()
  234. begin_binary_resource_stub.reset_mock()
  235. path = self.site.content.source_folder.child('favicon.ico')
  236. gen.generate_resource_at_path(path)
  237. called_with_resources = sorted([arg[0][0].path for arg in begin_binary_resource_stub.call_args_list])
  238. assert begin_binary_resource_stub.call_count == 1
  239. assert called_with_resources[0] == path
  240. def test_plugin_chaining(self):
  241. self.site.config.plugins = [
  242. 'hyde.tests.test_plugin.ConstantReturnPlugin',
  243. 'hyde.tests.test_plugin.NoReturnPlugin'
  244. ]
  245. path = self.site.content.source_folder.child('about.html')
  246. gen = Generator(self.site)
  247. gen.generate_resource_at_path(path)
  248. about = File(Folder(
  249. self.site.config.deploy_root_path).child('about.html'))
  250. assert about.read_all() == "Jam"
  251. def test_plugin_filters_begin_text_resource(self):
  252. def empty_return(self, resource, text=''):
  253. return text
  254. with patch.object(ConstantReturnPlugin, 'begin_text_resource', new=Mock(wraps=empty_return)) as mock1:
  255. with patch.object(NoReturnPlugin, 'begin_text_resource', new=Mock(wraps=empty_return)) as mock2:
  256. self.site.config.plugins = [
  257. 'hyde.tests.test_plugin.ConstantReturnPlugin',
  258. 'hyde.tests.test_plugin.NoReturnPlugin'
  259. ]
  260. self.site.config.constantreturn = Expando(dict(include_file_pattern="*.css"))
  261. self.site.config.noreturn = Expando(dict(include_file_pattern=["*.html", "*.txt"]))
  262. gen = Generator(self.site)
  263. gen.generate_all()
  264. mock1_args = sorted(set([arg[0][0].name for arg in mock1.call_args_list]))
  265. mock2_args = sorted(set([arg[0][0].name for arg in mock2.call_args_list]))
  266. assert len(mock1_args) == 1
  267. assert len(mock2_args) == 4
  268. assert mock1_args == ["site.css"]
  269. assert mock2_args == ["404.html", "about.html", "merry-christmas.html", "robots.txt"]
  270. def test_plugin_node_filters_begin_text_resource(self):
  271. def empty_return(*args, **kwargs):
  272. return None
  273. with patch.object(ConstantReturnPlugin, 'begin_text_resource', new=Mock(wraps=empty_return)) as mock1:
  274. with patch.object(NoReturnPlugin, 'begin_text_resource', new=Mock(wraps=empty_return)) as mock2:
  275. self.site.config.plugins = [
  276. 'hyde.tests.test_plugin.ConstantReturnPlugin',
  277. 'hyde.tests.test_plugin.NoReturnPlugin'
  278. ]
  279. self.site.config.constantreturn = Expando(dict(include_paths="media"))
  280. self.site.config.noreturn = Expando(dict(include_file_pattern="*.html", include_paths=["blog"]))
  281. gen = Generator(self.site)
  282. gen.generate_all()
  283. mock1_args = sorted(set([arg[0][0].name for arg in mock1.call_args_list]))
  284. mock2_args = sorted(set([arg[0][0].name for arg in mock2.call_args_list]))
  285. assert len(mock1_args) == 1
  286. assert len(mock2_args) == 1
  287. assert mock1_args == ["site.css"]
  288. assert mock2_args == ["merry-christmas.html"]