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.
 
 
 

421 lines
17 KiB

  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(
  29. 'sites/test_jinja').copy_contents_to(TEST_SITE)
  30. folders = []
  31. text_files = []
  32. binary_files = []
  33. with TEST_SITE.child_folder('content').walker as walker:
  34. @walker.folder_visitor
  35. def visit_folder(folder):
  36. folders.append(folder.path)
  37. @walker.file_visitor
  38. def visit_file(afile):
  39. if not afile.is_text:
  40. binary_files.append(afile.path)
  41. else:
  42. text_files.append(afile.path)
  43. cls.content_nodes = sorted(folders)
  44. cls.content_text_resources = sorted(text_files)
  45. cls.content_binary_resources = sorted(binary_files)
  46. @classmethod
  47. def teardown_class(cls):
  48. TEST_SITE.delete()
  49. def setUp(self):
  50. self.site = Site(TEST_SITE)
  51. self.site.config.plugins = ['test_plugin.PluginLoaderStub']
  52. def test_can_load_plugin_modules(self):
  53. assert not len(self.site.plugins)
  54. Plugin.load_all(self.site)
  55. assert len(self.site.plugins) == 1
  56. assert self.site.plugins[0].__class__.__name__ == 'PluginLoaderStub'
  57. def test_generator_loads_plugins(self):
  58. Generator(self.site)
  59. assert len(self.site.plugins) == 1
  60. def test_generator_template_registered_called(self):
  61. with patch.object(PluginLoaderStub,
  62. '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,
  68. 'begin_generation') as begin_generation_stub:
  69. gen = Generator(self.site)
  70. gen.generate_all()
  71. assert begin_generation_stub.call_count == 1
  72. def test_generator_template_begin_generation_called_for_single_res(self):
  73. with patch.object(PluginLoaderStub,
  74. 'begin_generation') as begin_generation_stub:
  75. gen = Generator(self.site)
  76. path = self.site.content.source_folder.child('about.html')
  77. gen.generate_resource_at_path(path)
  78. assert begin_generation_stub.call_count == 1
  79. def test_generator_template_begin_generation_called_for_single_node(self):
  80. with patch.object(PluginLoaderStub,
  81. 'begin_generation') as begin_generation_stub:
  82. gen = Generator(self.site)
  83. path = self.site.content.source_folder
  84. gen.generate_node_at_path(path)
  85. assert begin_generation_stub.call_count == 1
  86. def test_generator_template_generation_complete_called(self):
  87. with patch.object(PluginLoaderStub,
  88. 'generation_complete') as generation_complete_stub:
  89. gen = Generator(self.site)
  90. gen.generate_all()
  91. assert generation_complete_stub.call_count == 1
  92. def test_generator_template_generation_complete_called_for_single_rs(self):
  93. with patch.object(PluginLoaderStub,
  94. 'generation_complete') as generation_complete_stub:
  95. gen = Generator(self.site)
  96. path = self.site.content.source_folder.child('about.html')
  97. gen.generate_resource_at_path(path)
  98. assert generation_complete_stub.call_count == 1
  99. def test_generator_template_generation_complete_called_for_single_nd(self):
  100. with patch.object(PluginLoaderStub,
  101. 'generation_complete') as generation_complete_stub:
  102. gen = Generator(self.site)
  103. path = self.site.content.source_folder
  104. gen.generate_node_at_path(path)
  105. assert generation_complete_stub.call_count == 1
  106. def test_generator_template_begin_site_called(self):
  107. with patch.object(PluginLoaderStub, 'begin_site') as begin_site_stub:
  108. gen = Generator(self.site)
  109. gen.generate_all()
  110. assert begin_site_stub.call_count == 1
  111. def test_generator_template_begin_site_called_for_single_resource(self):
  112. with patch.object(PluginLoaderStub, 'begin_site') as begin_site_stub:
  113. gen = Generator(self.site)
  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_not_called_sngle_res_scnd_tm(self):
  118. with patch.object(PluginLoaderStub, 'begin_site') as begin_site_stub:
  119. gen = Generator(self.site)
  120. gen.generate_all()
  121. assert begin_site_stub.call_count == 1
  122. path = self.site.content.source_folder.child('about.html')
  123. gen.generate_resource_at_path(path)
  124. assert begin_site_stub.call_count == 1
  125. def test_generator_template_begin_site_called_for_single_node(self):
  126. with patch.object(PluginLoaderStub, 'begin_site') as begin_site_stub:
  127. gen = Generator(self.site)
  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_begin_site_not_call_for_sngl_nd_scnd_tm(self):
  132. with patch.object(PluginLoaderStub, 'begin_site') as begin_site_stub:
  133. gen = Generator(self.site)
  134. gen.generate_all()
  135. assert begin_site_stub.call_count == 1
  136. path = self.site.content.source_folder
  137. gen.generate_node_at_path(path)
  138. assert begin_site_stub.call_count == 1
  139. def test_generator_template_site_complete_called(self):
  140. with patch.object(PluginLoaderStub,
  141. 'site_complete') as site_complete_stub:
  142. gen = Generator(self.site)
  143. gen.generate_all()
  144. assert site_complete_stub.call_count == 1
  145. def test_generator_template_site_complete_called_for_single_resource(self):
  146. with patch.object(PluginLoaderStub,
  147. 'site_complete') as site_complete_stub:
  148. gen = Generator(self.site)
  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_complt_not_call_4_sngl_res_scnd_tm(self):
  153. with patch.object(PluginLoaderStub,
  154. 'site_complete') as site_complete_stub:
  155. gen = Generator(self.site)
  156. gen.generate_all()
  157. assert site_complete_stub.call_count == 1
  158. path = self.site.content.source_folder.child('about.html')
  159. gen.generate_resource_at_path(path)
  160. assert site_complete_stub.call_count == 1
  161. def test_generator_template_site_complete_called_for_single_node(self):
  162. with patch.object(PluginLoaderStub,
  163. 'site_complete') as site_complete_stub:
  164. gen = Generator(self.site)
  165. path = self.site.content.source_folder
  166. gen.generate_node_at_path(path)
  167. assert site_complete_stub.call_count == 1
  168. def test_generator_template_site_complete_not_call_4_sngl_nd_scnd_tm(self):
  169. with patch.object(PluginLoaderStub,
  170. 'site_complete') as site_complete_stub:
  171. gen = Generator(self.site)
  172. gen.generate_all()
  173. path = self.site.content.source_folder
  174. gen.generate_node_at_path(path)
  175. assert site_complete_stub.call_count == 1
  176. def test_generator_template_begin_node_called(self):
  177. with patch.object(PluginLoaderStub, 'begin_node') as begin_node_stub:
  178. gen = Generator(self.site)
  179. gen.generate_all()
  180. assert begin_node_stub.call_count == len(self.content_nodes)
  181. called_with_nodes = sorted(
  182. [arg[0][0].path for arg in begin_node_stub.call_args_list])
  183. assert called_with_nodes == self.content_nodes
  184. def test_generator_template_begin_node_called_for_single_resource(self):
  185. with patch.object(PluginLoaderStub, 'begin_node') as begin_node_stub:
  186. gen = Generator(self.site)
  187. gen.generate_resource_at_path(
  188. self.site.content.source_folder.child('about.html'))
  189. assert begin_node_stub.call_count == len(self.content_nodes)
  190. def test_generator_template_begin_node_not_called_4_sngl_res_scnd_tm(self):
  191. with patch.object(PluginLoaderStub, 'begin_node') as begin_node_stub:
  192. gen = Generator(self.site)
  193. gen.generate_all()
  194. assert begin_node_stub.call_count == len(self.content_nodes)
  195. gen.generate_resource_at_path(
  196. self.site.content.source_folder.child('about.html'))
  197. assert begin_node_stub.call_count == len(
  198. self.content_nodes) # No extra calls
  199. def test_generator_template_node_complete_called(self):
  200. with patch.object(PluginLoaderStub,
  201. 'node_complete') as node_complete_stub:
  202. gen = Generator(self.site)
  203. gen.generate_all()
  204. assert node_complete_stub.call_count == len(self.content_nodes)
  205. called_with_nodes = sorted(
  206. [arg[0][0].path for arg in node_complete_stub.call_args_list])
  207. assert called_with_nodes == self.content_nodes
  208. def test_generator_template_node_complete_called_for_single_resource(self):
  209. with patch.object(PluginLoaderStub,
  210. 'node_complete') as node_complete_stub:
  211. gen = Generator(self.site)
  212. gen.generate_resource_at_path(
  213. self.site.content.source_folder.child('about.html'))
  214. assert node_complete_stub.call_count == len(self.content_nodes)
  215. def test_generator_template_node_complete_not_cal_4_sngl_res_scnd_tm(self):
  216. with patch.object(PluginLoaderStub,
  217. 'node_complete') as node_complete_stub:
  218. gen = Generator(self.site)
  219. gen.generate_all()
  220. assert node_complete_stub.call_count == len(self.content_nodes)
  221. gen.generate_resource_at_path(
  222. self.site.content.source_folder.child('about.html'))
  223. assert node_complete_stub.call_count == len(
  224. self.content_nodes) # No extra calls
  225. def test_generator_template_begin_text_resource_called(self):
  226. with patch.object(PluginLoaderStub,
  227. 'begin_text_resource') as begin_text_resource_stub:
  228. begin_text_resource_stub.reset_mock()
  229. begin_text_resource_stub.return_value = ''
  230. gen = Generator(self.site)
  231. gen.generate_all()
  232. called_with_resources = sorted(
  233. [arg[0][0].path for arg in
  234. begin_text_resource_stub.call_args_list])
  235. assert set(called_with_resources) == set(
  236. self.content_text_resources)
  237. def test_generator_template_begin_text_resource_called_for_sngl_res(self):
  238. with patch.object(PluginLoaderStub,
  239. 'begin_text_resource') as begin_text_resource_stub:
  240. begin_text_resource_stub.return_value = ''
  241. gen = Generator(self.site)
  242. gen.generate_all()
  243. begin_text_resource_stub.reset_mock()
  244. path = self.site.content.source_folder.child('about.html')
  245. gen = Generator(self.site)
  246. gen.generate_resource_at_path(path, incremental=True)
  247. called_with_resources = sorted(
  248. [arg[0][0].path for arg in
  249. begin_text_resource_stub.call_args_list])
  250. assert begin_text_resource_stub.call_count == 1
  251. assert called_with_resources[0] == path
  252. def test_generator_template_begin_binary_resource_called(self):
  253. with patch.object(PluginLoaderStub, 'begin_binary_resource') as \
  254. begin_binary_resource_stub:
  255. gen = Generator(self.site)
  256. gen.generate_all()
  257. called_with_resources = sorted(
  258. [arg[0][0].path for arg in
  259. begin_binary_resource_stub.call_args_list])
  260. assert begin_binary_resource_stub.call_count == len(
  261. self.content_binary_resources)
  262. assert called_with_resources == self.content_binary_resources
  263. def test_generator_template_begin_binary_resource_called_4_sngl_res(self):
  264. with patch.object(PluginLoaderStub, 'begin_binary_resource') as \
  265. begin_binary_resource_stub:
  266. gen = Generator(self.site)
  267. gen.generate_all()
  268. begin_binary_resource_stub.reset_mock()
  269. path = self.site.content.source_folder.child('favicon.ico')
  270. gen.generate_resource_at_path(path)
  271. called_with_resources = sorted(
  272. [arg[0][0].path for arg in
  273. begin_binary_resource_stub.call_args_list])
  274. assert begin_binary_resource_stub.call_count == 1
  275. assert called_with_resources[0] == path
  276. def test_plugin_chaining(self):
  277. self.site.config.plugins = [
  278. 'test_plugin.ConstantReturnPlugin',
  279. 'test_plugin.NoReturnPlugin'
  280. ]
  281. path = self.site.content.source_folder.child('about.html')
  282. gen = Generator(self.site)
  283. gen.generate_resource_at_path(path)
  284. about = File(Folder(
  285. self.site.config.deploy_root_path).child('about.html'))
  286. assert about.read_all() == "Jam"
  287. def test_plugin_filters_begin_text_resource(self):
  288. def empty_return(self, resource, text=''):
  289. return text
  290. with patch.object(ConstantReturnPlugin, 'begin_text_resource',
  291. new=Mock(wraps=empty_return)) as mock1:
  292. with patch.object(NoReturnPlugin, 'begin_text_resource',
  293. new=Mock(wraps=empty_return)) as mock2:
  294. self.site.config.plugins = [
  295. 'test_plugin.ConstantReturnPlugin',
  296. 'test_plugin.NoReturnPlugin'
  297. ]
  298. self.site.config.constantreturn = Expando(
  299. dict(include_file_pattern="*.css"))
  300. self.site.config.noreturn = Expando(
  301. dict(include_file_pattern=["*.html", "*.txt"]))
  302. gen = Generator(self.site)
  303. gen.generate_all()
  304. mock1_args = sorted(
  305. set([arg[0][0].name for arg in mock1.call_args_list]))
  306. mock2_args = sorted(
  307. set([arg[0][0].name for arg in mock2.call_args_list]))
  308. assert len(mock1_args) == 1
  309. assert len(mock2_args) == 4
  310. assert mock1_args == ["site.css"]
  311. assert mock2_args == [
  312. "404.html", "about.html",
  313. "merry-christmas.html", "robots.txt"]
  314. def test_plugin_node_filters_begin_text_resource(self):
  315. def empty_return(*args, **kwargs):
  316. return None
  317. with patch.object(ConstantReturnPlugin, 'begin_text_resource',
  318. new=Mock(wraps=empty_return)) as mock1:
  319. with patch.object(NoReturnPlugin, 'begin_text_resource',
  320. new=Mock(wraps=empty_return)) as mock2:
  321. self.site.config.plugins = [
  322. 'test_plugin.ConstantReturnPlugin',
  323. 'test_plugin.NoReturnPlugin'
  324. ]
  325. self.site.config.constantreturn = Expando(
  326. dict(include_paths="media"))
  327. self.site.config.noreturn = Expando(
  328. dict(include_file_pattern="*.html",
  329. include_paths=["blog"]))
  330. gen = Generator(self.site)
  331. gen.generate_all()
  332. mock1_args = sorted(
  333. set([arg[0][0].name for arg in mock1.call_args_list]))
  334. mock2_args = sorted(
  335. set([arg[0][0].name for arg in mock2.call_args_list]))
  336. assert len(mock1_args) == 1
  337. assert len(mock2_args) == 1
  338. assert mock1_args == ["site.css"]
  339. assert mock2_args == ["merry-christmas.html"]