nanoc 4.7.10 → 4.7.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CONTRIBUTING.md +17 -0
  3. data/.github/ISSUE_TEMPLATE.md +23 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +18 -0
  5. data/.gitignore +8 -0
  6. data/.rspec +3 -0
  7. data/.rubocop.yml +174 -0
  8. data/.travis.yml +27 -0
  9. data/Gemfile +4 -3
  10. data/NEWS.md +11 -0
  11. data/Rakefile +5 -2
  12. data/lib/nanoc/base/entities/dependency.rb +5 -3
  13. data/lib/nanoc/base/entities/layout.rb +1 -1
  14. data/lib/nanoc/base/repos/dependency_store.rb +64 -28
  15. data/lib/nanoc/base/services/dependency_tracker.rb +1 -1
  16. data/lib/nanoc/base/views/config_view.rb +4 -0
  17. data/lib/nanoc/checking/checks/external_links.rb +3 -6
  18. data/lib/nanoc/cli.rb +0 -2
  19. data/lib/nanoc/cli/commands/shell.rb +2 -3
  20. data/lib/nanoc/filters/colorize_syntax/colorizers.rb +4 -1
  21. data/lib/nanoc/telemetry/table.rb +1 -1
  22. data/lib/nanoc/version.rb +1 -1
  23. data/nanoc.gemspec +1 -5
  24. data/scripts/release +95 -0
  25. data/{test → spec/nanoc}/base/core_ext/array_spec.rb +5 -14
  26. data/{test → spec/nanoc}/base/core_ext/hash_spec.rb +6 -15
  27. data/{test → spec/nanoc}/base/core_ext/pathname_spec.rb +0 -0
  28. data/spec/nanoc/base/core_ext/string_spec.rb +23 -0
  29. data/spec/nanoc/base/directed_graph_spec.rb +291 -0
  30. data/spec/nanoc/base/entities/identifiable_collection_spec.rb +56 -0
  31. data/spec/nanoc/base/entities/item_spec.rb +8 -0
  32. data/spec/nanoc/base/entities/layout_spec.rb +8 -0
  33. data/spec/nanoc/base/repos/dependency_store_spec.rb +166 -21
  34. data/spec/nanoc/base/views/config_view_spec.rb +29 -1
  35. data/spec/nanoc/cli/commands/shell_spec.rb +23 -8
  36. data/spec/nanoc/filters/less_spec.rb +1 -1
  37. data/spec/nanoc/regressions/gh_1185_spec.rb +22 -0
  38. data/spec/nanoc/telemetry/table_spec.rb +22 -0
  39. data/spec/spec_helper.rb +5 -6
  40. data/test/base/test_item_array.rb +0 -35
  41. data/test/checking/checks/test_external_links.rb +0 -14
  42. data/test/filters/test_coffeescript.rb +0 -2
  43. data/test/filters/test_handlebars.rb +0 -4
  44. data/test/filters/test_uglify_js.rb +0 -4
  45. data/test/helper.rb +0 -6
  46. data/test/helpers/test_blogging.rb +66 -26
  47. data/test/helpers/test_xml_sitemap.rb +23 -7
  48. metadata +16 -9
  49. data/Gemfile.lock +0 -433
  50. data/test/base/core_ext/string_spec.rb +0 -25
  51. data/test/base/test_item.rb +0 -40
  52. data/test/base/test_layout.rb +0 -16
@@ -5,7 +5,7 @@ module Nanoc::Int
5
5
  class DependencyTracker
6
6
  include Nanoc::Int::ContractsSupport
7
7
 
8
- C_OBJ = C::Or[Nanoc::Int::Item, Nanoc::Int::Layout]
8
+ C_OBJ = C::Or[Nanoc::Int::Item, Nanoc::Int::Layout, Nanoc::Int::Configuration]
9
9
  C_ATTR = C::Or[C::IterOf[Symbol], C::Bool]
10
10
  C_ARGS = C::KeywordArgs[raw_content: C::Optional[C::Bool], attributes: C::Optional[C_ATTR], compiled_content: C::Optional[C::Bool], path: C::Optional[C::Bool]]
11
11
 
@@ -18,6 +18,7 @@ module Nanoc
18
18
 
19
19
  # @see Hash#fetch
20
20
  def fetch(key, fallback = NONE, &_block)
21
+ @context.dependency_tracker.bounce(unwrap, attributes: [key])
21
22
  @config.fetch(key) do
22
23
  if !fallback.equal?(NONE)
23
24
  fallback
@@ -31,16 +32,19 @@ module Nanoc
31
32
 
32
33
  # @see Hash#key?
33
34
  def key?(key)
35
+ @context.dependency_tracker.bounce(unwrap, attributes: [key])
34
36
  @config.key?(key)
35
37
  end
36
38
 
37
39
  # @see Hash#[]
38
40
  def [](key)
41
+ @context.dependency_tracker.bounce(unwrap, attributes: [key])
39
42
  @config[key]
40
43
  end
41
44
 
42
45
  # @see Hash#each
43
46
  def each(&block)
47
+ @context.dependency_tracker.bounce(unwrap, attributes: true)
44
48
  @config.each(&block)
45
49
  end
46
50
  end
@@ -69,13 +69,10 @@ module ::Nanoc::Checking::Checks
69
69
  begin
70
70
  Timeout.timeout(timeouts[i]) do
71
71
  res = request_url_once(url)
72
- if res.code == '405'
73
- res = request_url_once(url, Net::HTTP::Get)
74
- end
75
72
  end
76
73
  rescue => e
77
74
  last_err = e
78
- next # can not allow
75
+ next
79
76
  end
80
77
 
81
78
  if res.code =~ /^3..$/
@@ -122,8 +119,8 @@ module ::Nanoc::Checking::Checks
122
119
  path
123
120
  end
124
121
 
125
- def request_url_once(url, req_method = Net::HTTP::Head)
126
- req = req_method.new(path_for_url(url))
122
+ def request_url_once(url)
123
+ req = Net::HTTP::Get.new(path_for_url(url))
127
124
  http = Net::HTTP.new(url.host, url.port)
128
125
  if url.instance_of? URI::HTTPS
129
126
  http.use_ssl = true
data/lib/nanoc/cli.rb CHANGED
@@ -78,8 +78,6 @@ module Nanoc::CLI
78
78
  add_after_setup_proc(block)
79
79
  end
80
80
 
81
- protected
82
-
83
81
  # Makes the command-line interface ready for use.
84
82
  #
85
83
  # @return [void]
@@ -6,19 +6,18 @@ aliases 'console'
6
6
  description "
7
7
  Open an IRB shell on a context that contains @items, @layouts, and @config.
8
8
  "
9
+ flag :p, :preprocess, 'run preprocessor'
9
10
 
10
11
  module Nanoc::CLI::Commands
11
12
  class Shell < ::Nanoc::CLI::CommandRunner
12
13
  def run
13
14
  require 'pry'
14
15
 
15
- load_site
16
+ load_site(preprocess: options[:preprocess])
16
17
 
17
18
  Nanoc::Int::Context.new(env).pry
18
19
  end
19
20
 
20
- protected
21
-
22
21
  def env
23
22
  self.class.env_for_site(site)
24
23
  end
@@ -166,7 +166,10 @@ module Nanoc::Filters::ColorizeSyntax::Colorizers
166
166
  code1 = element.xpath('code').first
167
167
  return if code1.nil?
168
168
 
169
- pre = code1.xpath('pre').first
169
+ div = code1.xpath('div').first
170
+
171
+ # For Rouge 2.x and 1.x, respectively
172
+ pre = (div || code1).xpath('pre').first
170
173
  return if pre.nil?
171
174
 
172
175
  code2 = pre.xpath('code').first
@@ -13,7 +13,7 @@ module Nanoc::Telemetry
13
13
  [].tap do |lines|
14
14
  lines << row_to_s(@rows[0], column_lengths)
15
15
  lines << separator(column_lengths)
16
- lines.concat(@rows.map { |r| row_to_s(r, column_lengths) })
16
+ lines.concat(@rows.drop(1).map { |r| row_to_s(r, column_lengths) })
17
17
  end.join("\n")
18
18
  end
19
19
 
data/lib/nanoc/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Nanoc
4
4
  # The current Nanoc version.
5
- VERSION = '4.7.10'
5
+ VERSION = '4.7.11'
6
6
  end
data/nanoc.gemspec CHANGED
@@ -13,11 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.email = 'denis.defreyne@stoneship.org'
14
14
  s.license = 'MIT'
15
15
 
16
- s.files =
17
- Dir['[A-Z]*'] +
18
- Dir['doc/yardoc_{templates,handlers}/**/*'] +
19
- Dir['{bin,lib,tasks,test,spec}/**/*'] +
20
- ['nanoc.gemspec']
16
+ s.files = `git ls-files -z`.split("\x0")
21
17
  s.executables = ['nanoc']
22
18
  s.require_paths = ['lib']
23
19
 
data/scripts/release ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'fileutils'
5
+ require 'octokit'
6
+
7
+ def run(*args)
8
+ puts 'I will execute the following:'
9
+ puts ' ' + args.map { |a| a =~ /\s/ ? a.inspect : a }.join(' ')
10
+ print 'Is this correct? [y/N] '
11
+ res = gets
12
+ unless res.strip.casecmp('y').zero?
13
+ $stderr.puts 'Answer was not Y; release aborted.'
14
+ exit 1
15
+ end
16
+
17
+ system('echo', *args)
18
+ system(*args)
19
+
20
+ print 'Continue? [y/N] '
21
+ res = gets
22
+ unless res.strip.casecmp('y').zero?
23
+ $stderr.puts 'Answer was not Y; release aborted.'
24
+ exit 1
25
+ end
26
+ end
27
+
28
+ puts '=== Logging in to GitHub’s API…'
29
+ client = Octokit::Client.new(netrc: true)
30
+ puts
31
+
32
+ puts '=== Deleting old *.gem files…'
33
+ Dir['*.gem'].each do |fn|
34
+ puts " #{fn}…"
35
+ FileUtils.rm_f(fn)
36
+ end
37
+ puts
38
+
39
+ puts '=== Verifying presence of release date…'
40
+ unless File.readlines('NEWS.md').drop(2).first =~ / \(\d{4}-\d{2}-\d{2}\)$/
41
+ $stderr.puts 'No proper release date found!'
42
+ exit 1
43
+ end
44
+ puts
45
+
46
+ puts '=== Building new gem…'
47
+ run('gem', 'build', 'nanoc.gemspec')
48
+ puts
49
+
50
+ puts '=== Reading version…'
51
+ require './lib/nanoc/version'
52
+ puts "Version = #{Nanoc::VERSION}"
53
+ puts
54
+
55
+ puts '=== Verifying that release does not yet exist…'
56
+ releases = client.releases('nanoc/nanoc')
57
+ release = releases.find { |r| r.tag_name == Nanoc::VERSION }
58
+ if release
59
+ $stderr.puts 'Release already exists!'
60
+ $stderr.puts 'ABORTED!'
61
+ exit 1
62
+ end
63
+ puts
64
+
65
+ puts '=== Creating Git tag…'
66
+ run('git', 'tag', '--sign', '--annotate', Nanoc::VERSION, '--message', "Version #{Nanoc::VERSION}")
67
+ puts
68
+
69
+ puts '=== Pushing Git data…'
70
+ run('git', 'push', 'origin', '--tags')
71
+ puts
72
+
73
+ puts '=== Pushing gem…'
74
+ run('gem', 'push', "nanoc-#{Nanoc::VERSION}.gem")
75
+ puts
76
+
77
+ puts '=== Reading release notes…'
78
+ release_notes =
79
+ File.readlines('NEWS.md')
80
+ .drop(4)
81
+ .take_while { |l| l !~ /^## / }
82
+ .join
83
+ puts
84
+
85
+ puts '=== Creating release on GitHub…'
86
+ sleep 3 # Give GitHub some time to detect the new tag
87
+ is_prerelease = Nanoc::VERSION =~ /a|b|rc/ || Nanoc::VERSION =~ /^0/
88
+ client.create_release(
89
+ 'nanoc/nanoc', Nanoc::VERSION,
90
+ prerelease: !is_prerelease.nil?,
91
+ body: release_notes
92
+ )
93
+ puts
94
+
95
+ puts 'DONE!'
@@ -1,34 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'helper'
4
-
5
3
  describe 'Array#__nanoc_symbolize_keys_recursively' do
6
4
  it 'should convert keys to symbols' do
7
5
  array_old = [:abc, 'xyz', { 'foo' => 'bar', :baz => :qux }]
8
6
  array_new = [:abc, 'xyz', { foo: 'bar', baz: :qux }]
9
- array_old.__nanoc_symbolize_keys_recursively.must_equal array_new
7
+ expect(array_old.__nanoc_symbolize_keys_recursively).to eql(array_new)
10
8
  end
11
9
  end
12
10
 
13
11
  describe 'Array#__nanoc_freeze_recursively' do
14
- include Nanoc::TestHelpers
15
-
16
12
  it 'should prevent first-level elements from being modified' do
17
13
  array = [:a, %i[b c], :d]
18
14
  array.__nanoc_freeze_recursively
19
15
 
20
- assert_raises_frozen_error do
21
- array[0] = 123
22
- end
16
+ expect { array[0] = 123 }.to raise_frozen_error
23
17
  end
24
18
 
25
19
  it 'should prevent second-level elements from being modified' do
26
20
  array = [:a, %i[b c], :d]
27
21
  array.__nanoc_freeze_recursively
28
22
 
29
- assert_raises_frozen_error do
30
- array[1][0] = 123
31
- end
23
+ expect { array[1][0] = 123 }.to raise_frozen_error
32
24
  end
33
25
 
34
26
  it 'should not freeze infinitely' do
@@ -37,8 +29,7 @@ describe 'Array#__nanoc_freeze_recursively' do
37
29
 
38
30
  a.__nanoc_freeze_recursively
39
31
 
40
- assert a.frozen?
41
- assert a[0].frozen?
42
- assert_equal a, a[0]
32
+ expect(a).to be_frozen
33
+ expect(a[0]).to be_frozen
43
34
  end
44
35
  end
@@ -1,40 +1,32 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'helper'
4
-
5
3
  describe 'Hash#__nanoc_symbolize_keys_recursively' do
6
4
  it 'should convert keys to symbols' do
7
5
  hash_old = { 'foo' => 'bar' }
8
6
  hash_new = { foo: 'bar' }
9
- hash_old.__nanoc_symbolize_keys_recursively.must_equal hash_new
7
+ expect(hash_old.__nanoc_symbolize_keys_recursively).to eql(hash_new)
10
8
  end
11
9
 
12
10
  it 'should not require string keys' do
13
11
  hash_old = { Time.now => 'abc' }
14
12
  hash_new = hash_old
15
- hash_old.__nanoc_symbolize_keys_recursively.must_equal hash_new
13
+ expect(hash_old.__nanoc_symbolize_keys_recursively).to eql(hash_new)
16
14
  end
17
15
  end
18
16
 
19
17
  describe 'Hash#__nanoc_freeze_recursively' do
20
- include Nanoc::TestHelpers
21
-
22
18
  it 'should prevent first-level elements from being modified' do
23
19
  hash = { a: { b: :c } }
24
20
  hash.__nanoc_freeze_recursively
25
21
 
26
- assert_raises_frozen_error do
27
- hash[:a] = 123
28
- end
22
+ expect { hash[:a] = 123 }.to raise_frozen_error
29
23
  end
30
24
 
31
25
  it 'should prevent second-level elements from being modified' do
32
26
  hash = { a: { b: :c } }
33
27
  hash.__nanoc_freeze_recursively
34
28
 
35
- assert_raises_frozen_error do
36
- hash[:a][:b] = 123
37
- end
29
+ expect { hash[:a][:b] = 123 }.to raise_frozen_error
38
30
  end
39
31
 
40
32
  it 'should not freeze infinitely' do
@@ -43,8 +35,7 @@ describe 'Hash#__nanoc_freeze_recursively' do
43
35
 
44
36
  a.__nanoc_freeze_recursively
45
37
 
46
- assert a.frozen?
47
- assert a[:x].frozen?
48
- assert_equal a, a[:x]
38
+ expect(a).to be_frozen
39
+ expect(a[0]).to be_frozen
49
40
  end
50
41
  end
File without changes
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe 'String#__nanoc_cleaned_identifier' do
4
+ it 'should not convert already clean paths' do
5
+ expect('/foo/bar/'.__nanoc_cleaned_identifier).to eql('/foo/bar/')
6
+ end
7
+
8
+ it 'should prepend slash if necessary' do
9
+ expect('foo/bar/'.__nanoc_cleaned_identifier).to eql('/foo/bar/')
10
+ end
11
+
12
+ it 'should append slash if necessary' do
13
+ expect('/foo/bar'.__nanoc_cleaned_identifier).to eql('/foo/bar/')
14
+ end
15
+
16
+ it 'should remove double slashes at start' do
17
+ expect('//foo/bar/'.__nanoc_cleaned_identifier).to eql('/foo/bar/')
18
+ end
19
+
20
+ it 'should remove double slashes at end' do
21
+ expect('/foo/bar//'.__nanoc_cleaned_identifier).to eql('/foo/bar/')
22
+ end
23
+ end
@@ -65,4 +65,295 @@ describe Nanoc::Int::DirectedGraph do
65
65
  it { is_expected.to eq([2, 3, 4, 5]) }
66
66
  end
67
67
  end
68
+
69
+ describe '#all_paths' do
70
+ subject { graph.all_paths.to_a }
71
+
72
+ context 'no cycles' do
73
+ example do
74
+ expect(subject).to contain_exactly(
75
+ [1],
76
+ [2],
77
+ [3],
78
+ )
79
+ end
80
+ end
81
+
82
+ context 'one cycle without head' do
83
+ before do
84
+ graph.add_edge(1, 2)
85
+ graph.add_edge(2, 1)
86
+ end
87
+
88
+ example do
89
+ expect(subject).to contain_exactly(
90
+ [1],
91
+ [1, 2],
92
+ [1, 2, 1],
93
+ [2],
94
+ [2, 1],
95
+ [2, 1, 2],
96
+ [3],
97
+ )
98
+ end
99
+ end
100
+
101
+ context 'one cycle with head' do
102
+ before do
103
+ graph.add_edge(1, 2)
104
+ graph.add_edge(2, 3)
105
+ graph.add_edge(3, 2)
106
+ end
107
+
108
+ example do
109
+ expect(subject).to contain_exactly(
110
+ [1],
111
+ [1, 2],
112
+ [1, 2, 3],
113
+ [1, 2, 3, 2],
114
+ [2],
115
+ [2, 3],
116
+ [2, 3, 2],
117
+ [3],
118
+ [3, 2],
119
+ [3, 2, 3],
120
+ )
121
+ end
122
+ end
123
+
124
+ context 'one cycle with tail' do
125
+ before do
126
+ graph.add_edge(1, 2)
127
+ graph.add_edge(2, 20)
128
+ graph.add_edge(20, 21)
129
+ graph.add_edge(2, 3)
130
+ graph.add_edge(3, 1)
131
+ end
132
+
133
+ example do
134
+ expect(subject).to contain_exactly(
135
+ [1],
136
+ [1, 2],
137
+ [1, 2, 20],
138
+ [1, 2, 20, 21],
139
+ [1, 2, 3],
140
+ [1, 2, 3, 1],
141
+ [2],
142
+ [2, 20],
143
+ [2, 20, 21],
144
+ [2, 3],
145
+ [2, 3, 1],
146
+ [2, 3, 1, 2],
147
+ [3],
148
+ [3, 1],
149
+ [3, 1, 2],
150
+ [3, 1, 2, 20],
151
+ [3, 1, 2, 20, 21],
152
+ [3, 1, 2, 3],
153
+ [20],
154
+ [20, 21],
155
+ [21],
156
+ )
157
+ end
158
+ end
159
+
160
+ context 'large cycle' do
161
+ before do
162
+ graph.add_edge(1, 2)
163
+ graph.add_edge(2, 3)
164
+ graph.add_edge(3, 4)
165
+ graph.add_edge(4, 5)
166
+ graph.add_edge(5, 1)
167
+ end
168
+
169
+ example do
170
+ expect(subject).to contain_exactly(
171
+ [1],
172
+ [1, 2],
173
+ [1, 2, 3],
174
+ [1, 2, 3, 4],
175
+ [1, 2, 3, 4, 5],
176
+ [1, 2, 3, 4, 5, 1],
177
+ [2],
178
+ [2, 3],
179
+ [2, 3, 4],
180
+ [2, 3, 4, 5],
181
+ [2, 3, 4, 5, 1],
182
+ [2, 3, 4, 5, 1, 2],
183
+ [3],
184
+ [3, 4],
185
+ [3, 4, 5],
186
+ [3, 4, 5, 1],
187
+ [3, 4, 5, 1, 2],
188
+ [3, 4, 5, 1, 2, 3],
189
+ [4],
190
+ [4, 5],
191
+ [4, 5, 1],
192
+ [4, 5, 1, 2],
193
+ [4, 5, 1, 2, 3],
194
+ [4, 5, 1, 2, 3, 4],
195
+ [5],
196
+ [5, 1],
197
+ [5, 1, 2],
198
+ [5, 1, 2, 3],
199
+ [5, 1, 2, 3, 4],
200
+ [5, 1, 2, 3, 4, 5],
201
+ )
202
+ end
203
+ end
204
+
205
+ context 'large cycle with head' do
206
+ before do
207
+ graph.add_edge(1, 2)
208
+ graph.add_edge(2, 3)
209
+ graph.add_edge(3, 4)
210
+ graph.add_edge(4, 5)
211
+ graph.add_edge(5, 2)
212
+ end
213
+
214
+ example do
215
+ expect(subject).to contain_exactly(
216
+ [1],
217
+ [1, 2],
218
+ [1, 2, 3],
219
+ [1, 2, 3, 4],
220
+ [1, 2, 3, 4, 5],
221
+ [1, 2, 3, 4, 5, 2],
222
+ [2],
223
+ [2, 3],
224
+ [2, 3, 4],
225
+ [2, 3, 4, 5],
226
+ [2, 3, 4, 5, 2],
227
+ [3],
228
+ [3, 4],
229
+ [3, 4, 5],
230
+ [3, 4, 5, 2],
231
+ [3, 4, 5, 2, 3],
232
+ [4],
233
+ [4, 5],
234
+ [4, 5, 2],
235
+ [4, 5, 2, 3],
236
+ [4, 5, 2, 3, 4],
237
+ [5],
238
+ [5, 2],
239
+ [5, 2, 3],
240
+ [5, 2, 3, 4],
241
+ [5, 2, 3, 4, 5],
242
+ )
243
+ end
244
+ end
245
+ end
246
+
247
+ describe '#dfs_from' do
248
+ subject do
249
+ [].tap do |ps|
250
+ graph.dfs_from(1) do |p|
251
+ ps << p
252
+ end
253
+ end
254
+ end
255
+
256
+ context 'no cycles' do
257
+ example do
258
+ expect(subject).to contain_exactly(
259
+ [1],
260
+ )
261
+ end
262
+ end
263
+
264
+ context 'one cycle without head' do
265
+ before do
266
+ graph.add_edge(1, 2)
267
+ graph.add_edge(2, 1)
268
+ end
269
+
270
+ example do
271
+ expect(subject).to contain_exactly(
272
+ [1],
273
+ [1, 2],
274
+ [1, 2, 1],
275
+ )
276
+ end
277
+ end
278
+
279
+ context 'one cycle with head' do
280
+ before do
281
+ graph.add_edge(1, 2)
282
+ graph.add_edge(2, 3)
283
+ graph.add_edge(3, 2)
284
+ end
285
+
286
+ example do
287
+ expect(subject).to contain_exactly(
288
+ [1],
289
+ [1, 2],
290
+ [1, 2, 3],
291
+ [1, 2, 3, 2],
292
+ )
293
+ end
294
+ end
295
+
296
+ context 'one cycle with tail' do
297
+ before do
298
+ graph.add_edge(1, 2)
299
+ graph.add_edge(2, 20)
300
+ graph.add_edge(20, 21)
301
+ graph.add_edge(2, 3)
302
+ graph.add_edge(3, 1)
303
+ end
304
+
305
+ example do
306
+ expect(subject).to contain_exactly(
307
+ [1],
308
+ [1, 2],
309
+ [1, 2, 20],
310
+ [1, 2, 20, 21],
311
+ [1, 2, 3],
312
+ [1, 2, 3, 1],
313
+ )
314
+ end
315
+ end
316
+
317
+ context 'large cycle' do
318
+ before do
319
+ graph.add_edge(1, 2)
320
+ graph.add_edge(2, 3)
321
+ graph.add_edge(3, 4)
322
+ graph.add_edge(4, 5)
323
+ graph.add_edge(5, 1)
324
+ end
325
+
326
+ example do
327
+ expect(subject).to contain_exactly(
328
+ [1],
329
+ [1, 2],
330
+ [1, 2, 3],
331
+ [1, 2, 3, 4],
332
+ [1, 2, 3, 4, 5],
333
+ [1, 2, 3, 4, 5, 1],
334
+ )
335
+ end
336
+ end
337
+
338
+ context 'large cycle with head' do
339
+ before do
340
+ graph.add_edge(1, 2)
341
+ graph.add_edge(2, 3)
342
+ graph.add_edge(3, 4)
343
+ graph.add_edge(4, 5)
344
+ graph.add_edge(5, 2)
345
+ end
346
+
347
+ example do
348
+ expect(subject).to contain_exactly(
349
+ [1],
350
+ [1, 2],
351
+ [1, 2, 3],
352
+ [1, 2, 3, 4],
353
+ [1, 2, 3, 4, 5],
354
+ [1, 2, 3, 4, 5, 2],
355
+ )
356
+ end
357
+ end
358
+ end
68
359
  end