nanoc 4.4.5 → 4.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -2
  3. data/Gemfile.lock +37 -18
  4. data/NEWS.md +6 -0
  5. data/Rakefile +8 -20
  6. data/lib/nanoc/base/entities/code_snippet.rb +0 -2
  7. data/lib/nanoc/base/entities/item_rep.rb +4 -22
  8. data/lib/nanoc/base/entities/processing_actions/snapshot.rb +9 -7
  9. data/lib/nanoc/base/entities/rule_memory.rb +15 -7
  10. data/lib/nanoc/base/entities/snapshot_def.rb +2 -8
  11. data/lib/nanoc/base/repos/store.rb +2 -28
  12. data/lib/nanoc/base/services/checksummer.rb +9 -10
  13. data/lib/nanoc/base/services/compiler.rb +14 -16
  14. data/lib/nanoc/base/services/executor.rb +2 -13
  15. data/lib/nanoc/base/views/mixins/with_reps_view_mixin.rb +1 -1
  16. data/lib/nanoc/checking/checks/external_links.rb +2 -1
  17. data/lib/nanoc/cli/commands/compile.rb +8 -14
  18. data/lib/nanoc/extra/parallel_collection.rb +57 -0
  19. data/lib/nanoc/extra.rb +1 -0
  20. data/lib/nanoc/filters/mustache.rb +1 -1
  21. data/lib/nanoc/rule_dsl/recording_executor.rb +6 -34
  22. data/lib/nanoc/rule_dsl/rule_memory_calculator.rb +42 -12
  23. data/lib/nanoc/spec.rb +1 -1
  24. data/lib/nanoc/version.rb +1 -1
  25. data/nanoc.gemspec +1 -2
  26. data/spec/contributors_spec.rb +18 -0
  27. data/spec/nanoc/base/checksummer_spec.rb +381 -0
  28. data/spec/nanoc/base/compiler_spec.rb +181 -0
  29. data/spec/nanoc/base/entities/configuration_spec.rb +49 -0
  30. data/spec/nanoc/base/entities/content_spec.rb +193 -0
  31. data/spec/nanoc/base/entities/document_spec.rb +206 -0
  32. data/spec/nanoc/base/entities/identifier_spec.rb +460 -0
  33. data/spec/nanoc/base/entities/item_rep_spec.rb +226 -0
  34. data/spec/nanoc/base/entities/item_spec.rb +3 -0
  35. data/spec/nanoc/base/entities/layout_spec.rb +3 -0
  36. data/spec/nanoc/base/entities/lazy_value_spec.rb +106 -0
  37. data/spec/nanoc/base/entities/outdatedness_status_spec.rb +113 -0
  38. data/spec/nanoc/base/entities/pattern_spec.rb +125 -0
  39. data/spec/nanoc/base/entities/processing_action_spec.rb +9 -0
  40. data/spec/nanoc/base/entities/processing_actions/filter_spec.rb +18 -0
  41. data/spec/nanoc/base/entities/processing_actions/layout_spec.rb +18 -0
  42. data/spec/nanoc/base/entities/processing_actions/snapshot_spec.rb +32 -0
  43. data/spec/nanoc/base/entities/props_spec.rb +195 -0
  44. data/spec/nanoc/base/entities/rule_memory_spec.rb +131 -0
  45. data/spec/nanoc/base/entities/site_spec.rb +73 -0
  46. data/spec/nanoc/base/feature_spec.rb +107 -0
  47. data/spec/nanoc/base/filter_spec.rb +99 -0
  48. data/spec/nanoc/base/item_rep_writer_spec.rb +131 -0
  49. data/spec/nanoc/base/plugin_registry_spec.rb +29 -0
  50. data/spec/nanoc/base/repos/checksum_store_spec.rb +133 -0
  51. data/spec/nanoc/base/repos/compiled_content_cache_spec.rb +55 -0
  52. data/spec/nanoc/base/repos/config_loader_spec.rb +243 -0
  53. data/spec/nanoc/base/repos/dependency_store_spec.rb +195 -0
  54. data/spec/nanoc/base/repos/site_loader_spec.rb +214 -0
  55. data/spec/nanoc/base/services/dependency_tracker_spec.rb +238 -0
  56. data/spec/nanoc/base/services/executor_spec.rb +495 -0
  57. data/spec/nanoc/base/services/item_rep_router_spec.rb +134 -0
  58. data/spec/nanoc/base/services/item_rep_selector_spec.rb +169 -0
  59. data/spec/nanoc/base/services/outdatedness_checker_spec.rb +370 -0
  60. data/spec/nanoc/base/services/outdatedness_rules_spec.rb +432 -0
  61. data/spec/nanoc/base/services/pruner_spec.rb +105 -0
  62. data/spec/nanoc/base/services/temp_filename_factory_spec.rb +87 -0
  63. data/spec/nanoc/base/views/config_view_spec.rb +96 -0
  64. data/spec/nanoc/base/views/document_view_spec.rb +332 -0
  65. data/spec/nanoc/base/views/identifiable_collection_view_spec.rb +190 -0
  66. data/spec/nanoc/base/views/item_collection_with_reps_view_spec.rb +18 -0
  67. data/spec/nanoc/base/views/item_collection_without_reps_view_spec.rb +18 -0
  68. data/spec/nanoc/base/views/item_rep_collection_view_spec.rb +143 -0
  69. data/spec/nanoc/base/views/item_rep_view_spec.rb +265 -0
  70. data/spec/nanoc/base/views/item_view_spec.rb +341 -0
  71. data/spec/nanoc/base/views/layout_collection_view_spec.rb +18 -0
  72. data/spec/nanoc/base/views/layout_view_spec.rb +14 -0
  73. data/spec/nanoc/base/views/mutable_config_view_spec.rb +16 -0
  74. data/spec/nanoc/base/views/mutable_document_view_spec.rb +92 -0
  75. data/spec/nanoc/base/views/mutable_identifiable_collection_view_spec.rb +36 -0
  76. data/spec/nanoc/base/views/mutable_item_collection_view_spec.rb +49 -0
  77. data/spec/nanoc/base/views/mutable_item_view_spec.rb +22 -0
  78. data/spec/nanoc/base/views/mutable_layout_collection_view_spec.rb +49 -0
  79. data/spec/nanoc/base/views/mutable_layout_view_spec.rb +13 -0
  80. data/spec/nanoc/base/views/post_compile_item_rep_collection_view_spec.rb +4 -0
  81. data/spec/nanoc/base/views/post_compile_item_rep_view_spec.rb +137 -0
  82. data/spec/nanoc/base/views/post_compile_item_view_spec.rb +56 -0
  83. data/spec/nanoc/cli/commands/compile/file_action_printer_spec.rb +76 -0
  84. data/spec/nanoc/cli/commands/compile/timing_recorder_spec.rb +66 -0
  85. data/spec/nanoc/cli/commands/compile_spec.rb +64 -0
  86. data/spec/nanoc/cli/commands/deploy_spec.rb +327 -0
  87. data/spec/nanoc/cli/commands/shell_spec.rb +54 -0
  88. data/spec/nanoc/cli/commands/show_data_spec.rb +126 -0
  89. data/spec/nanoc/cli/commands/show_rules_spec.rb +112 -0
  90. data/spec/nanoc/cli/commands/view_spec.rb +58 -0
  91. data/spec/nanoc/data_sources/filesystem_spec.rb +56 -0
  92. data/spec/nanoc/deploying/fog_spec.rb +193 -0
  93. data/spec/nanoc/extra/parallel_collection_spec.rb +108 -0
  94. data/spec/nanoc/filters/colorize_syntax/rouge_spec.rb +195 -0
  95. data/spec/nanoc/filters/less_spec.rb +120 -0
  96. data/spec/nanoc/helpers/blogging_spec.rb +216 -0
  97. data/spec/nanoc/helpers/breadcrumbs_spec.rb +133 -0
  98. data/spec/nanoc/helpers/capturing_spec.rb +181 -0
  99. data/spec/nanoc/helpers/child_parent_spec.rb +105 -0
  100. data/spec/nanoc/helpers/filtering_spec.rb +72 -0
  101. data/spec/nanoc/helpers/html_escape_spec.rb +35 -0
  102. data/spec/nanoc/helpers/link_to_spec.rb +275 -0
  103. data/spec/nanoc/helpers/rendering_spec.rb +141 -0
  104. data/spec/nanoc/helpers/tagging_spec.rb +104 -0
  105. data/spec/nanoc/helpers/text_spec.rb +58 -0
  106. data/spec/nanoc/integration/outdatedness_integration_spec.rb +208 -0
  107. data/spec/nanoc/regressions/gh_1015_spec.rb +17 -0
  108. data/spec/nanoc/regressions/gh_1031_spec.rb +54 -0
  109. data/spec/nanoc/regressions/gh_1035_spec.rb +33 -0
  110. data/spec/nanoc/regressions/gh_1040_spec.rb +22 -0
  111. data/spec/nanoc/regressions/gh_761_spec.rb +23 -0
  112. data/spec/nanoc/regressions/gh_767_spec.rb +19 -0
  113. data/spec/nanoc/regressions/gh_769_spec.rb +30 -0
  114. data/spec/nanoc/regressions/gh_776_spec.rb +43 -0
  115. data/spec/nanoc/regressions/gh_787_spec.rb +19 -0
  116. data/spec/nanoc/regressions/gh_795_spec.rb +19 -0
  117. data/spec/nanoc/regressions/gh_804_spec.rb +26 -0
  118. data/spec/nanoc/regressions/gh_807_spec.rb +17 -0
  119. data/spec/nanoc/regressions/gh_809_spec.rb +17 -0
  120. data/spec/nanoc/regressions/gh_813_spec.rb +22 -0
  121. data/spec/nanoc/regressions/gh_815_spec.rb +18 -0
  122. data/spec/nanoc/regressions/gh_828_spec.rb +23 -0
  123. data/spec/nanoc/regressions/gh_833_spec.rb +14 -0
  124. data/spec/nanoc/regressions/gh_841_spec.rb +15 -0
  125. data/spec/nanoc/regressions/gh_867_spec.rb +15 -0
  126. data/spec/nanoc/regressions/gh_882_spec.rb +29 -0
  127. data/spec/nanoc/regressions/gh_885_spec.rb +30 -0
  128. data/spec/nanoc/regressions/gh_891_spec.rb +26 -0
  129. data/spec/nanoc/regressions/gh_913_spec.rb +24 -0
  130. data/spec/nanoc/regressions/gh_928_spec.rb +5 -0
  131. data/spec/nanoc/regressions/gh_937_spec.rb +25 -0
  132. data/spec/nanoc/regressions/gh_942_spec.rb +21 -0
  133. data/spec/nanoc/regressions/gh_947_spec.rb +21 -0
  134. data/spec/nanoc/regressions/gh_948_spec.rb +16 -0
  135. data/spec/nanoc/regressions/gh_951_spec.rb +19 -0
  136. data/spec/nanoc/regressions/gh_954_spec.rb +33 -0
  137. data/spec/nanoc/regressions/gh_970a_spec.rb +17 -0
  138. data/spec/nanoc/regressions/gh_970b_spec.rb +50 -0
  139. data/spec/nanoc/regressions/gh_974_spec.rb +17 -0
  140. data/spec/nanoc/regressions/gh_981_spec.rb +21 -0
  141. data/spec/nanoc/rule_dsl/recording_executor_spec.rb +142 -0
  142. data/spec/nanoc/rule_dsl/rule_context_spec.rb +177 -0
  143. data/spec/nanoc/rule_dsl/rule_memory_calculator_spec.rb +233 -0
  144. data/spec/nanoc/rule_dsl/rules_collection_spec.rb +299 -0
  145. data/spec/regression_filenames_spec.rb +16 -0
  146. data/spec/spec_helper.rb +173 -0
  147. data/test/base/core_ext/array_spec.rb +2 -0
  148. data/test/base/core_ext/hash_spec.rb +2 -0
  149. data/test/base/core_ext/string_spec.rb +2 -0
  150. data/test/base/test_code_snippet.rb +2 -0
  151. data/test/base/test_compiler.rb +2 -0
  152. data/test/base/test_context.rb +4 -2
  153. data/test/base/test_data_source.rb +2 -0
  154. data/test/base/test_dependency_tracker.rb +2 -0
  155. data/test/base/test_directed_graph.rb +2 -0
  156. data/test/base/test_filter.rb +7 -5
  157. data/test/base/test_item.rb +2 -0
  158. data/test/base/test_item_array.rb +3 -1
  159. data/test/base/test_layout.rb +2 -0
  160. data/test/base/test_memoization.rb +2 -0
  161. data/test/base/test_notification_center.rb +2 -0
  162. data/test/base/test_outdatedness_checker.rb +2 -0
  163. data/test/base/test_plugin.rb +2 -0
  164. data/test/base/test_site.rb +2 -0
  165. data/test/base/test_store.rb +2 -0
  166. data/test/checking/checks/test_css.rb +2 -0
  167. data/test/checking/checks/test_external_links.rb +4 -2
  168. data/test/checking/checks/test_html.rb +2 -0
  169. data/test/checking/checks/test_internal_links.rb +5 -3
  170. data/test/checking/checks/test_mixed_content.rb +2 -0
  171. data/test/checking/checks/test_stale.rb +2 -0
  172. data/test/checking/test_check.rb +2 -0
  173. data/test/checking/test_dsl.rb +2 -0
  174. data/test/checking/test_runner.rb +2 -0
  175. data/test/cli/commands/test_check.rb +2 -0
  176. data/test/cli/commands/test_compile.rb +2 -0
  177. data/test/cli/commands/test_create_site.rb +2 -0
  178. data/test/cli/commands/test_help.rb +2 -0
  179. data/test/cli/commands/test_info.rb +2 -0
  180. data/test/cli/commands/test_prune.rb +2 -0
  181. data/test/cli/test_cleaning_stream.rb +2 -0
  182. data/test/cli/test_cli.rb +11 -9
  183. data/test/cli/test_error_handler.rb +2 -0
  184. data/test/cli/test_logger.rb +2 -0
  185. data/test/data_sources/test_filesystem.rb +8 -6
  186. data/test/data_sources/test_filesystem_tools.rb +2 -0
  187. data/test/deploying/test_fog.rb +2 -0
  188. data/test/deploying/test_rsync.rb +4 -2
  189. data/test/extra/core_ext/test_pathname.rb +2 -0
  190. data/test/extra/core_ext/test_time.rb +2 -0
  191. data/test/extra/test_link_collector.rb +2 -0
  192. data/test/extra/test_piper.rb +2 -0
  193. data/test/filters/colorize_syntax/test_coderay.rb +2 -0
  194. data/test/filters/colorize_syntax/test_common.rb +2 -0
  195. data/test/filters/colorize_syntax/test_pygmentize.rb +2 -0
  196. data/test/filters/colorize_syntax/test_pygments.rb +2 -0
  197. data/test/filters/colorize_syntax/test_simon.rb +2 -0
  198. data/test/filters/test_asciidoc.rb +2 -0
  199. data/test/filters/test_bluecloth.rb +2 -0
  200. data/test/filters/test_coffeescript.rb +2 -0
  201. data/test/filters/test_erb.rb +7 -5
  202. data/test/filters/test_erubis.rb +6 -4
  203. data/test/filters/test_haml.rb +7 -5
  204. data/test/filters/test_handlebars.rb +2 -0
  205. data/test/filters/test_kramdown.rb +2 -0
  206. data/test/filters/test_markaby.rb +2 -0
  207. data/test/filters/test_maruku.rb +2 -0
  208. data/test/filters/test_mustache.rb +4 -2
  209. data/test/filters/test_pandoc.rb +2 -0
  210. data/test/filters/test_rainpress.rb +2 -0
  211. data/test/filters/test_rdiscount.rb +2 -0
  212. data/test/filters/test_rdoc.rb +2 -0
  213. data/test/filters/test_redcarpet.rb +2 -0
  214. data/test/filters/test_redcloth.rb +2 -0
  215. data/test/filters/test_relativize_paths.rb +2 -0
  216. data/test/filters/test_rubypants.rb +2 -0
  217. data/test/filters/test_sass.rb +4 -2
  218. data/test/filters/test_slim.rb +4 -2
  219. data/test/filters/test_typogruby.rb +2 -0
  220. data/test/filters/test_uglify_js.rb +2 -0
  221. data/test/filters/test_xsl.rb +2 -0
  222. data/test/filters/test_yui_compressor.rb +5 -3
  223. data/test/helpers/test_blogging.rb +2 -0
  224. data/test/helpers/test_capturing.rb +2 -0
  225. data/test/helpers/test_link_to.rb +2 -0
  226. data/test/helpers/test_xml_sitemap.rb +2 -0
  227. data/test/rule_dsl/test_action_provider.rb +2 -0
  228. data/test/rule_dsl/test_compiler_dsl.rb +6 -4
  229. data/test/rule_dsl/test_rule.rb +2 -0
  230. data/test/rule_dsl/test_rules_collection.rb +2 -0
  231. data/test/test_gem.rb +2 -0
  232. metadata +124 -17
  233. data/test/base/test_item_rep.rb +0 -156
@@ -0,0 +1,216 @@
1
+ describe Nanoc::Helpers::Blogging, helper: true do
2
+ before do
3
+ allow(ctx.dependency_tracker).to receive(:enter)
4
+ allow(ctx.dependency_tracker).to receive(:exit)
5
+ end
6
+
7
+ describe '#articles' do
8
+ subject { helper.articles }
9
+
10
+ before do
11
+ ctx.create_item('blah', { kind: 'item' }, '/0/')
12
+ ctx.create_item('blah blah', { kind: 'article' }, '/1/')
13
+ ctx.create_item('blah blah blah', { kind: 'article' }, '/2/')
14
+ end
15
+
16
+ it 'returns the two articles' do
17
+ expect(subject.map(&:identifier)).to match_array(['/1/', '/2/'])
18
+ end
19
+ end
20
+
21
+ describe '#sorted_articles' do
22
+ subject { helper.sorted_articles }
23
+
24
+ before do
25
+ attrs = { kind: 'item' }
26
+ ctx.create_item('blah', attrs, '/0/')
27
+
28
+ attrs = { kind: 'article', created_at: (Date.today - 1).to_s }
29
+ ctx.create_item('blah blah', attrs, '/1/')
30
+
31
+ attrs = { kind: 'article', created_at: (Time.now - 500).to_s }
32
+ ctx.create_item('blah blah blah', attrs, '/2/')
33
+ end
34
+
35
+ it 'returns the two articles in descending order' do
36
+ expect(subject.map(&:identifier)).to eq(['/2/', '/1/'])
37
+ end
38
+ end
39
+
40
+ describe '#url_for' do
41
+ subject { helper.url_for(ctx.items['/stuff/']) }
42
+
43
+ let(:item_attributes) { {} }
44
+
45
+ before do
46
+ item = ctx.create_item('Stuff', item_attributes, '/stuff/')
47
+ ctx.create_rep(item, '/rep/path/stuff.html')
48
+
49
+ ctx.config[:base_url] = base_url
50
+ end
51
+
52
+ context 'without base_url' do
53
+ let(:base_url) { nil }
54
+
55
+ it 'raises' do
56
+ expect { subject }.to raise_error(Nanoc::Error)
57
+ end
58
+ end
59
+
60
+ context 'with base_url' do
61
+ let(:base_url) { 'http://url.base' }
62
+
63
+ context 'with custom_url_in_feed' do
64
+ let(:item_attributes) do
65
+ { custom_url_in_feed: 'http://example.com/stuff.html' }
66
+ end
67
+
68
+ it 'returns custom URL' do
69
+ expect(subject).to eql('http://example.com/stuff.html')
70
+ end
71
+ end
72
+
73
+ context 'without custom_url_in_feed' do
74
+ context 'with custom_path_in_feed' do
75
+ let(:item_attributes) do
76
+ { custom_path_in_feed: '/stuff.html' }
77
+ end
78
+
79
+ it 'returns base URL + custom path' do
80
+ expect(subject).to eql('http://url.base/stuff.html')
81
+ end
82
+ end
83
+
84
+ context 'without custom_path_in_feed' do
85
+ it 'returns base URL + path' do
86
+ expect(subject).to eql('http://url.base/rep/path/stuff.html')
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ describe '#feed_url' do
94
+ subject { helper.feed_url }
95
+
96
+ let(:item_attributes) { {} }
97
+
98
+ before do
99
+ ctx.item = ctx.create_item('Feed', item_attributes, '/feed/')
100
+ ctx.create_rep(ctx.item, '/feed.xml')
101
+
102
+ ctx.config[:base_url] = base_url
103
+ end
104
+
105
+ context 'without base_url' do
106
+ let(:base_url) { nil }
107
+
108
+ it 'raises' do
109
+ expect { subject }.to raise_error(Nanoc::Error)
110
+ end
111
+ end
112
+
113
+ context 'with base_url' do
114
+ let(:base_url) { 'http://url.base' }
115
+
116
+ context 'with feed_url' do
117
+ let(:item_attributes) do
118
+ { feed_url: 'http://custom.feed.url/feed.rss' }
119
+ end
120
+
121
+ it 'returns custom URL' do
122
+ expect(subject).to eql('http://custom.feed.url/feed.rss')
123
+ end
124
+ end
125
+
126
+ context 'without feed_url' do
127
+ it 'returns base URL + path' do
128
+ expect(subject).to eql('http://url.base/feed.xml')
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ describe '#attribute_to_time' do
135
+ subject { helper.attribute_to_time(arg) }
136
+
137
+ let(:noon_s) { 1_446_903_076 }
138
+ let(:beginning_of_day_s) { 1_446_854_400 }
139
+
140
+ let(:around_noon_local) { Time.at(noon_s - Time.at(noon_s).utc_offset) }
141
+ let(:around_noon_utc) { Time.at(noon_s) }
142
+ let(:beginning_of_day_utc) { Time.at(beginning_of_day_s) }
143
+
144
+ context 'with Time instance' do
145
+ let(:arg) { around_noon_utc }
146
+ it { is_expected.to eql(around_noon_utc) }
147
+ end
148
+
149
+ context 'with Date instance' do
150
+ let(:arg) { Date.new(2015, 11, 7) }
151
+ it { is_expected.to eql(beginning_of_day_utc) }
152
+ end
153
+
154
+ context 'with DateTime instance' do
155
+ let(:arg) { DateTime.new(2015, 11, 7, 13, 31, 16) }
156
+ it { is_expected.to eql(around_noon_utc) }
157
+ end
158
+
159
+ context 'with string' do
160
+ let(:arg) { '2015-11-7 13:31:16' }
161
+ it { is_expected.to eql(around_noon_local) }
162
+ end
163
+ end
164
+
165
+ describe '#atom_tag_for' do
166
+ subject { helper.atom_tag_for(ctx.items['/stuff/']) }
167
+
168
+ let(:item_attributes) { { created_at: '2015-05-19 12:34:56' } }
169
+ let(:item_rep_path) { '/stuff.xml' }
170
+ let(:base_url) { 'http://url.base' }
171
+
172
+ before do
173
+ item = ctx.create_item('Stuff', item_attributes, '/stuff/')
174
+ ctx.create_rep(item, item_rep_path)
175
+
176
+ ctx.config[:base_url] = base_url
177
+ end
178
+
179
+ context 'item with path' do
180
+ let(:item_rep_path) { '/stuff.xml' }
181
+ it { is_expected.to eql('tag:url.base,2015-05-19:/stuff.xml') }
182
+ end
183
+
184
+ context 'item without path' do
185
+ let(:item_rep_path) { nil }
186
+ it { is_expected.to eql('tag:url.base,2015-05-19:/stuff/') }
187
+ end
188
+
189
+ context 'bare URL without subdir' do
190
+ let(:base_url) { 'http://url.base' }
191
+ it { is_expected.to eql('tag:url.base,2015-05-19:/stuff.xml') }
192
+ end
193
+
194
+ context 'bare URL with subdir' do
195
+ let(:base_url) { 'http://url.base/sub' }
196
+ it { is_expected.to eql('tag:url.base,2015-05-19:/sub/stuff.xml') }
197
+ end
198
+
199
+ context 'created_at is date' do
200
+ let(:item_attributes) do
201
+ { created_at: Date.parse('2015-05-19 12:34:56') }
202
+ end
203
+ it { is_expected.to eql('tag:url.base,2015-05-19:/stuff.xml') }
204
+ end
205
+
206
+ context 'created_at is time' do
207
+ let(:item_attributes) do
208
+ { created_at: Time.parse('2015-05-19 12:34:56') }
209
+ end
210
+ it { is_expected.to eql('tag:url.base,2015-05-19:/stuff.xml') }
211
+ end
212
+
213
+ # TODO: handle missing base_dir
214
+ # TODO: handle missing created_at
215
+ end
216
+ end
@@ -0,0 +1,133 @@
1
+ describe Nanoc::Helpers::Breadcrumbs, helper: true do
2
+ before do
3
+ allow(ctx.dependency_tracker).to receive(:enter)
4
+ allow(ctx.dependency_tracker).to receive(:exit)
5
+ end
6
+
7
+ describe '#breadcrumbs_trail' do
8
+ subject { helper.breadcrumbs_trail }
9
+
10
+ context 'legacy identifiers' do
11
+ context 'root' do
12
+ before do
13
+ ctx.create_item('root', {}, Nanoc::Identifier.new('/', type: :legacy))
14
+
15
+ ctx.item = ctx.items['/']
16
+ end
17
+
18
+ it 'returns an array with the item' do
19
+ expect(subject).to eql([ctx.items['/']])
20
+ end
21
+ end
22
+
23
+ context 'root and direct child' do
24
+ before do
25
+ ctx.create_item('child', {}, Nanoc::Identifier.new('/foo/', type: :legacy))
26
+ ctx.create_item('root', {}, Nanoc::Identifier.new('/', type: :legacy))
27
+
28
+ ctx.item = ctx.items['/foo/']
29
+ end
30
+
31
+ it 'returns an array with the items' do
32
+ expect(subject).to eql([ctx.items['/'], ctx.items['/foo/']])
33
+ end
34
+ end
35
+
36
+ context 'root, child and grandchild' do
37
+ before do
38
+ ctx.create_item('grandchild', {}, Nanoc::Identifier.new('/foo/bar/', type: :legacy))
39
+ ctx.create_item('child', {}, Nanoc::Identifier.new('/foo/', type: :legacy))
40
+ ctx.create_item('root', {}, Nanoc::Identifier.new('/', type: :legacy))
41
+
42
+ ctx.item = ctx.items['/foo/bar/']
43
+ end
44
+
45
+ it 'returns an array with the items' do
46
+ expect(subject).to eql([ctx.items['/'], ctx.items['/foo/'], ctx.items['/foo/bar/']])
47
+ end
48
+ end
49
+
50
+ context 'root, missing child and grandchild' do
51
+ before do
52
+ ctx.create_item('grandchild', {}, Nanoc::Identifier.new('/foo/bar/', type: :legacy))
53
+ ctx.create_item('root', {}, Nanoc::Identifier.new('/', type: :legacy))
54
+
55
+ ctx.item = ctx.items['/foo/bar/']
56
+ end
57
+
58
+ it 'returns an array with the items' do
59
+ expect(subject).to eql([ctx.items['/'], nil, ctx.items['/foo/bar/']])
60
+ end
61
+ end
62
+ end
63
+
64
+ context 'non-legacy identifiers' do
65
+ context 'root' do
66
+ before do
67
+ ctx.create_item('root', {}, Nanoc::Identifier.new('/index.md'))
68
+
69
+ ctx.item = ctx.items['/index.md']
70
+ end
71
+
72
+ it 'returns an array with the item' do
73
+ expect(subject).to eql([ctx.items['/index.md']])
74
+ end
75
+ end
76
+
77
+ context 'root and direct child' do
78
+ before do
79
+ ctx.create_item('child', {}, Nanoc::Identifier.new('/foo.md'))
80
+ ctx.create_item('root', {}, Nanoc::Identifier.new('/index.md'))
81
+
82
+ ctx.item = ctx.items['/foo.md']
83
+ end
84
+
85
+ it 'returns an array with the items' do
86
+ expect(subject).to eql([ctx.items['/index.md'], ctx.items['/foo.md']])
87
+ end
88
+ end
89
+
90
+ context 'root, child and grandchild' do
91
+ before do
92
+ ctx.create_item('grandchild', {}, Nanoc::Identifier.new('/foo/bar.md'))
93
+ ctx.create_item('child', {}, Nanoc::Identifier.new('/foo.md'))
94
+ ctx.create_item('root', {}, Nanoc::Identifier.new('/index.md'))
95
+
96
+ ctx.item = ctx.items['/foo/bar.md']
97
+ end
98
+
99
+ it 'returns an array with the items' do
100
+ expect(subject).to eql([ctx.items['/index.md'], ctx.items['/foo.md'], ctx.items['/foo/bar.md']])
101
+ end
102
+ end
103
+
104
+ context 'root, missing child and grandchild' do
105
+ before do
106
+ ctx.create_item('grandchild', {}, Nanoc::Identifier.new('/foo/bar.md'))
107
+ ctx.create_item('root', {}, Nanoc::Identifier.new('/index.md'))
108
+
109
+ ctx.item = ctx.items['/foo/bar.md']
110
+ end
111
+
112
+ it 'returns an array with the items' do
113
+ expect(subject).to eql([ctx.items['/index.md'], nil, ctx.items['/foo/bar.md']])
114
+ end
115
+ end
116
+
117
+ context 'index.md child' do
118
+ # No special handling of non-root index.* files.
119
+
120
+ before do
121
+ ctx.create_item('grandchild', {}, Nanoc::Identifier.new('/foo/index.md'))
122
+ ctx.create_item('root', {}, Nanoc::Identifier.new('/index.md'))
123
+
124
+ ctx.item = ctx.items['/foo/index.md']
125
+ end
126
+
127
+ it 'returns an array with the items' do
128
+ expect(subject).to eql([ctx.items['/index.md'], nil, ctx.items['/foo/index.md']])
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,181 @@
1
+ describe Nanoc::Helpers::Capturing, helper: true do
2
+ describe '#content_for' do
3
+ before do
4
+ ctx.item = ctx.create_item('some content', {}, '/about.md')
5
+ ctx.create_rep(ctx.item, '/about.html')
6
+ end
7
+
8
+ describe 'with name + block' do
9
+ let(:_erbout) { 'existing content' }
10
+
11
+ context 'only name given' do
12
+ subject { helper.content_for(:foo) { _erbout << 'foo' } }
13
+
14
+ it 'stores snapshot content' do
15
+ subject
16
+ expect(ctx.item.reps[:default].unwrap.snapshot_contents[:__capture_foo].string).to eql('foo')
17
+ end
18
+ end
19
+
20
+ context 'name and params given' do
21
+ subject { helper.content_for(:foo, params) { _erbout << 'foo' } }
22
+ let(:params) { raise 'overwrite me' }
23
+
24
+ context 'no existing behavior specified' do
25
+ let(:params) { {} }
26
+
27
+ it 'errors after two times' do
28
+ helper.content_for(:foo, params) { _erbout << 'foo' }
29
+ expect { helper.content_for(:foo, params) { _erbout << 'bar' } }.to raise_error(RuntimeError)
30
+ end
31
+ end
32
+
33
+ context 'existing behavior is :overwrite' do
34
+ let(:params) { { existing: :overwrite } }
35
+
36
+ it 'overwrites' do
37
+ helper.content_for(:foo, params) { _erbout << 'foo' }
38
+ helper.content_for(:foo, params) { _erbout << 'bar' }
39
+ expect(ctx.item.reps[:default].unwrap.snapshot_contents[:__capture_foo].string).to eql('bar')
40
+ end
41
+ end
42
+
43
+ context 'existing behavior is :append' do
44
+ let(:params) { { existing: :append } }
45
+
46
+ it 'appends' do
47
+ helper.content_for(:foo, params) { _erbout << 'foo' }
48
+ helper.content_for(:foo, params) { _erbout << 'bar' }
49
+ expect(ctx.item.reps[:default].unwrap.snapshot_contents[:__capture_foo].string).to eql('foobar')
50
+ end
51
+ end
52
+
53
+ context 'existing behavior is :error' do
54
+ let(:params) { { existing: :error } }
55
+
56
+ it 'errors after two times' do
57
+ helper.content_for(:foo, params) { _erbout << 'foo' }
58
+ expect { helper.content_for(:foo, params) { _erbout << 'bar' } }.to raise_error(RuntimeError)
59
+ end
60
+ end
61
+
62
+ context 'existing behavior is :something else' do
63
+ let(:params) { { existing: :donkey } }
64
+
65
+ it 'errors' do
66
+ expect { subject }.to raise_error(ArgumentError)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ describe 'with item + name' do
73
+ subject { helper.content_for(item, :foo) }
74
+
75
+ let(:_erbout) { 'existing content' }
76
+
77
+ context 'requesting for same item' do
78
+ let(:item) { ctx.item }
79
+
80
+ context 'nothing captured' do
81
+ it { is_expected.to be_nil }
82
+ end
83
+
84
+ context 'something captured' do
85
+ before do
86
+ helper.content_for(:foo) { _erbout << 'I have been captured!' }
87
+ end
88
+
89
+ it { is_expected.to eql('I have been captured!') }
90
+ end
91
+ end
92
+
93
+ context 'requesting for other item' do
94
+ let(:item) { ctx.items['/other.md'] }
95
+
96
+ before do
97
+ item = ctx.create_item('other content', {}, '/other.md')
98
+ ctx.create_rep(item, '/other.html')
99
+ end
100
+
101
+ context 'other item is not yet compiled' do
102
+ it 'raises an unmet dependency error' do
103
+ expect(ctx.dependency_tracker).to receive(:bounce).with(item.unwrap, compiled_content: true)
104
+ expect { subject }.to raise_error(FiberError)
105
+ end
106
+ end
107
+
108
+ context 'other item is compiled' do
109
+ before do
110
+ item.reps[:default].unwrap.compiled = true
111
+ item.reps[:default].unwrap.snapshot_contents[:__capture_foo] =
112
+ Nanoc::Int::TextualContent.new('other captured foo')
113
+ end
114
+
115
+ it 'returns the captured content' do
116
+ expect(ctx.dependency_tracker).to receive(:bounce).with(item.unwrap, compiled_content: true)
117
+ expect(subject).to eql('other captured foo')
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ describe '#capture' do
125
+ context 'with string' do
126
+ let(:_erbout) { 'existing content' }
127
+
128
+ subject { helper.capture { _erbout << 'new content' } }
129
+
130
+ it 'returns the appended content' do
131
+ expect(subject).to eql('new content')
132
+ end
133
+
134
+ it 'does not modify _erbout' do
135
+ expect { subject }.not_to change { _erbout }
136
+ end
137
+ end
138
+
139
+ context 'with array' do
140
+ let(:_erbout) { ['existing content'] }
141
+
142
+ shared_examples 'returns properly joined output' do
143
+ subject { helper.capture { _erbout << %w(new _ content) } }
144
+
145
+ it 'returns the appended content, joined' do
146
+ expect(subject).to eql('new_content')
147
+ end
148
+
149
+ it 'does not modify _erbout' do
150
+ expect { subject }.not_to change { _erbout.join('') }
151
+ end
152
+ end
153
+
154
+ context 'default output field separator' do
155
+ include_examples 'returns properly joined output'
156
+ end
157
+
158
+ context 'output field separator set to ,' do
159
+ around do |ex|
160
+ orig_output_field_separator = $OUTPUT_FIELD_SEPARATOR
161
+ $OUTPUT_FIELD_SEPARATOR = ','
162
+ ex.run
163
+ $OUTPUT_FIELD_SEPARATOR = orig_output_field_separator
164
+ end
165
+
166
+ include_examples 'returns properly joined output'
167
+ end
168
+
169
+ context 'output field separator set to nothing' do
170
+ around do |ex|
171
+ orig_output_field_separator = $OUTPUT_FIELD_SEPARATOR
172
+ $OUTPUT_FIELD_SEPARATOR = ''
173
+ ex.run
174
+ $OUTPUT_FIELD_SEPARATOR = orig_output_field_separator
175
+ end
176
+
177
+ include_examples 'returns properly joined output'
178
+ end
179
+ end
180
+ end
181
+ end
@@ -0,0 +1,105 @@
1
+ describe Nanoc::Helpers::ChildParent, helper: true do
2
+ describe '#children_of' do
3
+ subject { helper.children_of(item) }
4
+
5
+ let(:item) { ctx.create_item('some content', {}, identifier) }
6
+
7
+ context 'legacy identifier' do
8
+ let(:identifier) { Nanoc::Identifier.new('/foo/', type: :legacy) }
9
+
10
+ let!(:child_item) do
11
+ ctx.create_item('abc', {}, Nanoc::Identifier.new('/foo/a/', type: :legacy))
12
+ end
13
+
14
+ let!(:grandchild_item) do
15
+ ctx.create_item('def', {}, Nanoc::Identifier.new('/foo/a/b/', type: :legacy))
16
+ end
17
+
18
+ let!(:sibling_item) do
19
+ ctx.create_item('xyz', {}, Nanoc::Identifier.new('/bar/', type: :legacy))
20
+ end
21
+
22
+ it 'returns only direct children' do
23
+ expect(subject).to eql([child_item])
24
+ end
25
+ end
26
+
27
+ context 'full identifier' do
28
+ let(:identifier) { Nanoc::Identifier.new('/foo.md', type: :full) }
29
+
30
+ let!(:child_item) do
31
+ ctx.create_item('abc', {}, Nanoc::Identifier.new('/foo/a.md', type: :full))
32
+ end
33
+
34
+ let!(:grandchild_item) do
35
+ ctx.create_item('def', {}, Nanoc::Identifier.new('/foo/a/b.md', type: :full))
36
+ end
37
+
38
+ let!(:sibling_item) do
39
+ ctx.create_item('xyz', {}, Nanoc::Identifier.new('/bar.md', type: :full))
40
+ end
41
+
42
+ let!(:index_child_item) do
43
+ ctx.create_item('xyz', {}, Nanoc::Identifier.new('/foo/a/index.md', type: :full))
44
+ end
45
+
46
+ it 'returns only direct children' do
47
+ expect(subject).to eql([child_item])
48
+ end
49
+ end
50
+ end
51
+
52
+ describe '#parent_of' do
53
+ subject { helper.parent_of(item) }
54
+
55
+ let(:item) { ctx.create_item('some content', {}, identifier) }
56
+
57
+ context 'legacy identifier' do
58
+ let(:identifier) { Nanoc::Identifier.new('/foo/bar/', type: :legacy) }
59
+
60
+ let!(:parent_item) do
61
+ ctx.create_item('abc', {}, Nanoc::Identifier.new('/foo/', type: :legacy))
62
+ end
63
+
64
+ let!(:sibling_item) do
65
+ ctx.create_item('def', {}, Nanoc::Identifier.new('/foo/qux/', type: :legacy))
66
+ end
67
+
68
+ let!(:child_item) do
69
+ ctx.create_item('xyz', {}, Nanoc::Identifier.new('/foo/bar/asdf/', type: :legacy))
70
+ end
71
+
72
+ let!(:grandparent_item) do
73
+ ctx.create_item('opq', {}, Nanoc::Identifier.new('/', type: :legacy))
74
+ end
75
+
76
+ it 'returns parent' do
77
+ expect(subject).to eql(parent_item)
78
+ end
79
+ end
80
+
81
+ context 'full identifier' do
82
+ let(:identifier) { Nanoc::Identifier.new('/foo/bar.md', type: :full) }
83
+
84
+ let!(:parent_item) do
85
+ ctx.create_item('abc', {}, Nanoc::Identifier.new('/foo.md', type: :full))
86
+ end
87
+
88
+ let!(:sibling_item) do
89
+ ctx.create_item('def', {}, Nanoc::Identifier.new('/foo/qux.md', type: :full))
90
+ end
91
+
92
+ let!(:child_item) do
93
+ ctx.create_item('xyz', {}, Nanoc::Identifier.new('/foo/bar/asdf.md', type: :full))
94
+ end
95
+
96
+ let!(:grandparent_item) do
97
+ ctx.create_item('opq', {}, Nanoc::Identifier.new('/index.md', type: :full))
98
+ end
99
+
100
+ it 'returns parent' do
101
+ expect(subject).to eql(parent_item)
102
+ end
103
+ end
104
+ end
105
+ end