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,193 @@
1
+ describe Nanoc::Int::Content do
2
+ describe '.create' do
3
+ subject { described_class.create(arg, params) }
4
+
5
+ let(:params) { {} }
6
+
7
+ context 'nil arg' do
8
+ let(:arg) { nil }
9
+
10
+ it 'raises' do
11
+ expect { subject }.to raise_error(ArgumentError)
12
+ end
13
+ end
14
+
15
+ context 'content arg' do
16
+ let(:arg) { Nanoc::Int::TextualContent.new('foo') }
17
+
18
+ it { is_expected.to eql(arg) }
19
+ end
20
+
21
+ context 'with binary: true param' do
22
+ let(:arg) { '/foo.dat' }
23
+ let(:params) { { binary: true } }
24
+
25
+ it 'returns binary content' do
26
+ expect(subject).to be_a(Nanoc::Int::BinaryContent)
27
+ expect(subject.filename).to eql('/foo.dat')
28
+ end
29
+ end
30
+
31
+ context 'with binary: false param' do
32
+ context 'with filename param' do
33
+ let(:arg) { 'foo' }
34
+ let(:params) { { binary: false, filename: '/foo.md' } }
35
+
36
+ it 'returns textual content' do
37
+ expect(subject).to be_a(Nanoc::Int::TextualContent)
38
+ expect(subject.string).to eql('foo')
39
+ expect(subject.filename).to eql('/foo.md')
40
+ end
41
+ end
42
+
43
+ context 'without filename param' do
44
+ let(:arg) { 'foo' }
45
+ let(:params) { { binary: false } }
46
+
47
+ it 'returns textual content' do
48
+ expect(subject).to be_a(Nanoc::Int::TextualContent)
49
+ expect(subject.string).to eql('foo')
50
+ expect(subject.filename).to be_nil
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ describe Nanoc::Int::TextualContent do
58
+ describe '#initialize' do
59
+ context 'without filename' do
60
+ let(:content) { described_class.new('foo') }
61
+
62
+ it 'sets string and filename' do
63
+ expect(content.string).to eq('foo')
64
+ expect(content.filename).to be_nil
65
+ end
66
+ end
67
+
68
+ context 'with absolute filename' do
69
+ let(:content) { described_class.new('foo', filename: '/foo.md') }
70
+
71
+ it 'sets string and filename' do
72
+ expect(content.string).to eq('foo')
73
+ expect(content.filename).to eq('/foo.md')
74
+ end
75
+ end
76
+
77
+ context 'with relative filename' do
78
+ let(:content) { described_class.new('foo', filename: 'foo.md') }
79
+
80
+ it 'errors' do
81
+ expect { content }.to raise_error(ArgumentError)
82
+ end
83
+ end
84
+
85
+ context 'with proc' do
86
+ let(:content_proc) { -> { 'foo' } }
87
+ let(:content) { described_class.new(content_proc) }
88
+
89
+ it 'does not call the proc immediately' do
90
+ expect(content_proc).not_to receive(:call)
91
+
92
+ content
93
+ end
94
+
95
+ it 'sets string' do
96
+ expect(content_proc).to receive(:call).once.and_return('dataz')
97
+
98
+ expect(content.string).to eq('dataz')
99
+ end
100
+
101
+ it 'only calls the proc once' do
102
+ expect(content_proc).to receive(:call).once.and_return('dataz')
103
+
104
+ expect(content.string).to eq('dataz')
105
+ expect(content.string).to eq('dataz')
106
+ end
107
+ end
108
+ end
109
+
110
+ describe '#binary?' do
111
+ subject { content.binary? }
112
+ let(:content) { described_class.new('foo') }
113
+ it { is_expected.to eql(false) }
114
+ end
115
+
116
+ describe '#freeze' do
117
+ let(:content) { described_class.new('foo', filename: '/asdf.md') }
118
+
119
+ before do
120
+ content.freeze
121
+ end
122
+
123
+ it 'prevents changes to string' do
124
+ expect(content.string).to be_frozen
125
+ expect { content.string << 'asdf' }.to raise_frozen_error
126
+ end
127
+
128
+ it 'prevents changes to filename' do
129
+ expect(content.filename).to be_frozen
130
+ expect { content.filename << 'asdf' }.to raise_frozen_error
131
+ end
132
+
133
+ context 'with proc' do
134
+ let(:content) { described_class.new(proc { 'foo' }) }
135
+
136
+ it 'prevents changes to string' do
137
+ expect(content.string).to be_frozen
138
+ expect { content.string << 'asdf' }.to raise_frozen_error
139
+ end
140
+ end
141
+ end
142
+
143
+ describe 'marshalling' do
144
+ let(:content) { described_class.new('foo', filename: '/foo.md') }
145
+
146
+ it 'dumps as an array' do
147
+ expect(content.marshal_dump).to eq(['/foo.md', 'foo'])
148
+ end
149
+
150
+ it 'restores a dumped object' do
151
+ restored = Marshal.load(Marshal.dump(content))
152
+ expect(restored.string).to eq('foo')
153
+ expect(restored.filename).to eq('/foo.md')
154
+ end
155
+ end
156
+ end
157
+
158
+ describe Nanoc::Int::BinaryContent do
159
+ describe '#initialize' do
160
+ let(:content) { described_class.new('/foo.dat') }
161
+
162
+ it 'sets filename' do
163
+ expect(content.filename).to eql('/foo.dat')
164
+ end
165
+
166
+ context 'with relative filename' do
167
+ let(:content) { described_class.new('foo.dat') }
168
+
169
+ it 'errors' do
170
+ expect { content }.to raise_error(ArgumentError)
171
+ end
172
+ end
173
+ end
174
+
175
+ describe '#binary?' do
176
+ subject { content.binary? }
177
+ let(:content) { described_class.new('/foo.dat') }
178
+ it { is_expected.to eql(true) }
179
+ end
180
+
181
+ describe '#freeze' do
182
+ let(:content) { described_class.new('/foo.dat') }
183
+
184
+ before do
185
+ content.freeze
186
+ end
187
+
188
+ it 'prevents changes' do
189
+ expect(content.filename).to be_frozen
190
+ expect { content.filename << 'asdf' }.to raise_frozen_error
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,206 @@
1
+ shared_examples 'a document' do
2
+ describe '#initialize' do
3
+ let(:content_arg) { 'Hello world' }
4
+ let(:attributes_arg) { { 'title' => 'Home' } }
5
+ let(:identifier_arg) { '/home.md' }
6
+ let(:checksum_data_arg) { 'abcdef' }
7
+ let(:content_checksum_data_arg) { 'con-cs' }
8
+ let(:attributes_checksum_data_arg) { 'attr-cs' }
9
+
10
+ subject do
11
+ described_class.new(
12
+ content_arg,
13
+ attributes_arg,
14
+ identifier_arg,
15
+ checksum_data: checksum_data_arg,
16
+ content_checksum_data: content_checksum_data_arg,
17
+ attributes_checksum_data: attributes_checksum_data_arg,
18
+ )
19
+ end
20
+
21
+ describe 'content arg' do
22
+ context 'string' do
23
+ it 'converts content' do
24
+ expect(subject.content).to be_a(Nanoc::Int::TextualContent)
25
+ expect(subject.content.string).to eql('Hello world')
26
+ end
27
+ end
28
+
29
+ context 'content' do
30
+ let(:content_arg) { Nanoc::Int::TextualContent.new('foo') }
31
+
32
+ it 'reuses content' do
33
+ expect(subject.content).to equal(content_arg)
34
+ end
35
+ end
36
+ end
37
+
38
+ describe 'attributes arg' do
39
+ context 'hash' do
40
+ it 'symbolizes attributes' do
41
+ expect(subject.attributes).to eq(title: 'Home')
42
+ end
43
+ end
44
+
45
+ context 'proc' do
46
+ call_count = 0
47
+ let(:attributes_arg) do
48
+ proc do
49
+ call_count += 1
50
+ { 'title' => 'Home' }
51
+ end
52
+ end
53
+
54
+ before do
55
+ call_count = 0
56
+ end
57
+
58
+ it 'does not call the proc immediately' do
59
+ expect(call_count).to eql(0)
60
+ end
61
+
62
+ it 'symbolizes attributes' do
63
+ expect(subject.attributes).to eq(title: 'Home')
64
+ end
65
+
66
+ it 'only calls the proc once' do
67
+ subject.attributes
68
+ subject.attributes
69
+ expect(call_count).to eql(1)
70
+ end
71
+ end
72
+ end
73
+
74
+ describe 'identifier arg' do
75
+ context 'string' do
76
+ it 'converts identifier' do
77
+ expect(subject.identifier).to be_a(Nanoc::Identifier)
78
+ expect(subject.identifier.to_s).to eql('/home.md')
79
+ end
80
+ end
81
+
82
+ context 'identifier' do
83
+ let(:identifier_arg) { Nanoc::Identifier.new('/foo.md') }
84
+
85
+ it 'retains identifier' do
86
+ expect(subject.identifier).to equal(identifier_arg)
87
+ end
88
+ end
89
+ end
90
+
91
+ describe 'checksum_data arg' do
92
+ it 'reuses checksum_data' do
93
+ expect(subject.checksum_data).to eql(checksum_data_arg)
94
+ end
95
+ end
96
+
97
+ describe 'content_checksum_data arg' do
98
+ it 'reuses content_checksum_data' do
99
+ expect(subject.content_checksum_data).to eql(content_checksum_data_arg)
100
+ end
101
+ end
102
+
103
+ describe 'attributes_checksum_data arg' do
104
+ it 'reuses attributes_checksum_data' do
105
+ expect(subject.attributes_checksum_data).to eql(attributes_checksum_data_arg)
106
+ end
107
+ end
108
+ end
109
+
110
+ describe '#freeze' do
111
+ let(:content_arg) { 'Hallo' }
112
+ let(:attributes_arg) { { foo: { bar: 'asdf' } } }
113
+ let(:document) { described_class.new(content_arg, attributes_arg, '/foo.md') }
114
+
115
+ before do
116
+ document.freeze
117
+ end
118
+
119
+ it 'refuses changes to content' do
120
+ expect { document.instance_variable_set(:@content, 'hah') }.to raise_frozen_error
121
+ expect { document.content.string << 'hah' }.to raise_frozen_error
122
+ end
123
+
124
+ it 'refuses to change attributes' do
125
+ expect { document.instance_variable_set(:@attributes, a: 'Hi') }.to raise_frozen_error
126
+ expect { document.attributes[:title] = 'Bye' }.to raise_frozen_error
127
+ expect { document.attributes[:foo][:bar] = 'fdsa' }.to raise_frozen_error
128
+ end
129
+
130
+ it 'refuses to change identifier' do
131
+ expect { document.identifier = '/asdf' }.to raise_frozen_error
132
+ expect { document.identifier.to_s << '/omg' }.to raise_frozen_error
133
+ end
134
+
135
+ context 'binary content' do
136
+ let(:content_arg) { Nanoc::Int::BinaryContent.new(File.expand_path('foo.dat')) }
137
+
138
+ it 'refuses changes to content' do
139
+ expect { document.instance_variable_set(:@content, 'hah') }.to raise_frozen_error
140
+ expect { document.content.filename << 'hah' }.to raise_frozen_error
141
+ end
142
+ end
143
+
144
+ context 'attributes block' do
145
+ let(:attributes_arg) { proc { { foo: { bar: 'asdf' } } } }
146
+
147
+ it 'gives access to the attributes' do
148
+ expect(document.attributes).to eql(foo: { bar: 'asdf' })
149
+ end
150
+
151
+ it 'refuses to change attributes' do
152
+ expect { document.instance_variable_set(:@attributes, a: 'Hi') }.to raise_frozen_error
153
+ expect { document.attributes[:title] = 'Bye' }.to raise_frozen_error
154
+ expect { document.attributes[:foo][:bar] = 'fdsa' }.to raise_frozen_error
155
+ end
156
+ end
157
+ end
158
+
159
+ describe 'equality' do
160
+ let(:content_arg_a) { 'Hello world' }
161
+ let(:content_arg_b) { 'Bye world' }
162
+
163
+ let(:attributes_arg_a) { { 'title' => 'Home' } }
164
+ let(:attributes_arg_b) { { 'title' => 'About' } }
165
+
166
+ let(:identifier_arg_a) { '/home.md' }
167
+ let(:identifier_arg_b) { '/home.md' }
168
+
169
+ let(:document_a) { described_class.new(content_arg_a, attributes_arg_a, identifier_arg_a) }
170
+ let(:document_b) { described_class.new(content_arg_b, attributes_arg_b, identifier_arg_b) }
171
+
172
+ subject { document_a == document_b }
173
+
174
+ context 'same identifier' do
175
+ let(:identifier_arg_a) { '/home.md' }
176
+ let(:identifier_arg_b) { '/home.md' }
177
+
178
+ it { is_expected.to eql(true) }
179
+
180
+ it 'has same hashes' do
181
+ expect(document_a.hash).to eql(document_b.hash)
182
+ end
183
+ end
184
+
185
+ context 'different identifier' do
186
+ let(:identifier_arg_a) { '/home.md' }
187
+ let(:identifier_arg_b) { '/about.md' }
188
+
189
+ it { is_expected.to eql(false) }
190
+
191
+ it 'has different hashes' do
192
+ expect(document_a.hash).not_to eql(document_b.hash)
193
+ end
194
+ end
195
+
196
+ context 'comparing with non-document' do
197
+ let(:document_b) { nil }
198
+
199
+ it { is_expected.to eql(false) }
200
+
201
+ it 'has different hashes' do
202
+ expect(document_a.hash).not_to eql(document_b.hash)
203
+ end
204
+ end
205
+ end
206
+ end