/hyde/tests/test_plugin.py

http://github.com/hyde/hyde · Python · 370 lines · 280 code · 84 blank · 6 comment · 44 complexity · 4e11ba91863d82ce0cab25d73c99886f MD5 · raw file

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