cms_scanner 0.0.2

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 (147) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +6 -0
  5. data/.travis.yml +14 -0
  6. data/Gemfile +6 -0
  7. data/README.md +20 -0
  8. data/Rakefile +9 -0
  9. data/app/app.rb +4 -0
  10. data/app/controllers.rb +2 -0
  11. data/app/controllers/core.rb +46 -0
  12. data/app/controllers/core/cli_options.rb +68 -0
  13. data/app/controllers/interesting_files.rb +12 -0
  14. data/app/finders.rb +1 -0
  15. data/app/finders/interesting_files.rb +21 -0
  16. data/app/finders/interesting_files/fantastico_fileslist.rb +23 -0
  17. data/app/finders/interesting_files/headers.rb +15 -0
  18. data/app/finders/interesting_files/robots_txt.rb +22 -0
  19. data/app/finders/interesting_files/search_replace_db_2.rb +28 -0
  20. data/app/finders/interesting_files/xml_rpc.rb +62 -0
  21. data/app/formatters.rb +3 -0
  22. data/app/formatters/cli.rb +18 -0
  23. data/app/formatters/cli_no_colour.rb +15 -0
  24. data/app/formatters/json.rb +12 -0
  25. data/app/models.rb +5 -0
  26. data/app/models/fantastico_fileslist.rb +20 -0
  27. data/app/models/headers.rb +37 -0
  28. data/app/models/interesting_file.rb +30 -0
  29. data/app/models/robots_txt.rb +20 -0
  30. data/app/models/xml_rpc.rb +35 -0
  31. data/app/views/cli/core/finished.erb +4 -0
  32. data/app/views/cli/core/started.erb +3 -0
  33. data/app/views/cli/interesting_files/findings.erb +19 -0
  34. data/app/views/cli/scan_aborted.erb +4 -0
  35. data/app/views/json/core/finished.erb +3 -0
  36. data/app/views/json/core/started.erb +3 -0
  37. data/app/views/json/interesting_files/findings.erb +1 -0
  38. data/app/views/json/scan_aborted.erb +4 -0
  39. data/cms_scanner.gemspec +37 -0
  40. data/examples/views/cli/wp_custom/test.erb +1 -0
  41. data/examples/views/json/wp_custom/test.erb +1 -0
  42. data/examples/wpscan.rb +29 -0
  43. data/lib/cms_scanner.rb +71 -0
  44. data/lib/cms_scanner/browser.rb +68 -0
  45. data/lib/cms_scanner/browser/actions.rb +48 -0
  46. data/lib/cms_scanner/browser/options.rb +53 -0
  47. data/lib/cms_scanner/cache/file_store.rb +75 -0
  48. data/lib/cms_scanner/cache/typhoeus.rb +21 -0
  49. data/lib/cms_scanner/controller.rb +90 -0
  50. data/lib/cms_scanner/controllers.rb +34 -0
  51. data/lib/cms_scanner/errors/auth_errors.rb +15 -0
  52. data/lib/cms_scanner/finders.rb +5 -0
  53. data/lib/cms_scanner/finders/finder.rb +27 -0
  54. data/lib/cms_scanner/finders/finding.rb +32 -0
  55. data/lib/cms_scanner/finders/findings.rb +25 -0
  56. data/lib/cms_scanner/finders/independent_finder.rb +30 -0
  57. data/lib/cms_scanner/finders/independent_finders.rb +41 -0
  58. data/lib/cms_scanner/formatter.rb +118 -0
  59. data/lib/cms_scanner/formatter/buffer.rb +15 -0
  60. data/lib/cms_scanner/target.rb +33 -0
  61. data/lib/cms_scanner/target/platform.rb +2 -0
  62. data/lib/cms_scanner/target/platform/php.rb +39 -0
  63. data/lib/cms_scanner/target/platform/wordpress.rb +35 -0
  64. data/lib/cms_scanner/target/platform/wordpress/custom_directories.rb +62 -0
  65. data/lib/cms_scanner/target/server.rb +3 -0
  66. data/lib/cms_scanner/target/server/apache.rb +43 -0
  67. data/lib/cms_scanner/target/server/generic.rb +34 -0
  68. data/lib/cms_scanner/target/server/iis.rb +48 -0
  69. data/lib/cms_scanner/version.rb +4 -0
  70. data/lib/cms_scanner/web_site.rb +68 -0
  71. data/lib/helper.rb +24 -0
  72. data/spec/app/controllers/core_spec.rb +152 -0
  73. data/spec/app/controllers/interesting_files_spec.rb +50 -0
  74. data/spec/app/finders/interesting_files/fantastico_fileslist_spec.rb +68 -0
  75. data/spec/app/finders/interesting_files/headers_spec.rb +38 -0
  76. data/spec/app/finders/interesting_files/robots_txt_spec.rb +56 -0
  77. data/spec/app/finders/interesting_files/search_replace_db_2_spec.rb +55 -0
  78. data/spec/app/finders/interesting_files/xml_rpc_spec.rb +138 -0
  79. data/spec/app/finders/interesting_files_spec.rb +13 -0
  80. data/spec/app/formatters/cli_no_colour_spec.rb +17 -0
  81. data/spec/app/formatters/cli_spec.rb +21 -0
  82. data/spec/app/formatters/json_spec.rb +33 -0
  83. data/spec/app/models/fantastico_fileslist_spec.rb +32 -0
  84. data/spec/app/models/headers_spec.rb +52 -0
  85. data/spec/app/models/interesting_file_spec.rb +51 -0
  86. data/spec/app/models/robots_txt_spec.rb +28 -0
  87. data/spec/app/models/xml_rpc_spec.rb +47 -0
  88. data/spec/cache/.gitignore +4 -0
  89. data/spec/dummy_finders.rb +41 -0
  90. data/spec/fixtures/interesting_files/fantastico_fileslist/fantastico_fileslist.txt +12 -0
  91. data/spec/fixtures/interesting_files/file.txt +4 -0
  92. data/spec/fixtures/interesting_files/headers/interesting.txt +14 -0
  93. data/spec/fixtures/interesting_files/headers/no_interesting.txt +12 -0
  94. data/spec/fixtures/interesting_files/robots_txt/robots.txt +10 -0
  95. data/spec/fixtures/interesting_files/search_replace_db_2/searchreplacedb2.php +188 -0
  96. data/spec/fixtures/interesting_files/xml_rpc/homepage_in_scope_pingback.html +7 -0
  97. data/spec/fixtures/interesting_files/xml_rpc/homepage_out_of_scope_pingback.html +7 -0
  98. data/spec/fixtures/interesting_files/xml_rpc/xmlrpc.php +1 -0
  99. data/spec/fixtures/output.txt +0 -0
  100. data/spec/fixtures/target/platform/php/debug_log/debug.log +2 -0
  101. data/spec/fixtures/target/platform/php/fpd/wp_rss_functions.php +2 -0
  102. data/spec/fixtures/target/platform/wordpress/custom_directories/custom_w_spaces.html +10 -0
  103. data/spec/fixtures/target/platform/wordpress/custom_directories/default.html +14 -0
  104. data/spec/fixtures/target/platform/wordpress/custom_directories/https.html +12 -0
  105. data/spec/fixtures/target/platform/wordpress/detection/default.html +4 -0
  106. data/spec/fixtures/target/platform/wordpress/detection/not_wp.html +8 -0
  107. data/spec/fixtures/target/platform/wordpress/detection/wp_includes.html +3 -0
  108. data/spec/fixtures/target/server/apache/directory_listing/2.2.16.html +15 -0
  109. data/spec/fixtures/target/server/generic/server/apache/basic.txt +5 -0
  110. data/spec/fixtures/target/server/generic/server/iis/basic.txt +6 -0
  111. data/spec/fixtures/target/server/generic/server/not_detected.txt +3 -0
  112. data/spec/fixtures/target/server/iis/directory_listing/no_parent.html +3 -0
  113. data/spec/fixtures/target/server/iis/directory_listing/with_parent.html +3 -0
  114. data/spec/fixtures/views/base/ctrl/local.erb +1 -0
  115. data/spec/fixtures/views/base/ctrl/test.erb +3 -0
  116. data/spec/fixtures/views/base/global.erb +1 -0
  117. data/spec/fixtures/views/base/test.erb +2 -0
  118. data/spec/fixtures/views/based_format/test.erb +1 -0
  119. data/spec/fixtures/views/json/render_me.erb +4 -0
  120. data/spec/lib/browser_spec.rb +141 -0
  121. data/spec/lib/cache/file_store_spec.rb +101 -0
  122. data/spec/lib/cache/typhoeus_spec.rb +30 -0
  123. data/spec/lib/cms_scanner_spec.rb +45 -0
  124. data/spec/lib/controller_spec.rb +23 -0
  125. data/spec/lib/controllers_spec.rb +52 -0
  126. data/spec/lib/finders/findings_spec.rb +49 -0
  127. data/spec/lib/finders/independent_finders_spec.rb +98 -0
  128. data/spec/lib/formatter_spec.rb +136 -0
  129. data/spec/lib/sub_scanner_spec.rb +27 -0
  130. data/spec/lib/target/platforms_spec.rb +13 -0
  131. data/spec/lib/target/servers_spec.rb +13 -0
  132. data/spec/lib/target_spec.rb +50 -0
  133. data/spec/lib/web_site_spec.rb +124 -0
  134. data/spec/shared_examples.rb +11 -0
  135. data/spec/shared_examples/browser_actions.rb +32 -0
  136. data/spec/shared_examples/finding.rb +20 -0
  137. data/spec/shared_examples/formatter_buffer.rb +8 -0
  138. data/spec/shared_examples/formatter_class_methods.rb +26 -0
  139. data/spec/shared_examples/independent_finder.rb +33 -0
  140. data/spec/shared_examples/target/platform/php.rb +58 -0
  141. data/spec/shared_examples/target/platform/wordpress.rb +41 -0
  142. data/spec/shared_examples/target/platform/wordpress/custom_directories.rb +50 -0
  143. data/spec/shared_examples/target/server/apache.rb +33 -0
  144. data/spec/shared_examples/target/server/generic.rb +34 -0
  145. data/spec/shared_examples/target/server/iis.rb +38 -0
  146. data/spec/spec_helper.rb +41 -0
  147. metadata +432 -0
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::Finders::InterestingFile::SearchReplaceDB2 do
4
+
5
+ subject(:finder) { described_class.new(target) }
6
+ let(:target) { CMSScanner::Target.new(url) }
7
+ let(:url) { 'http://example.com/' }
8
+ let(:file) { url + 'searchreplacedb2.php' }
9
+ let(:fixtures) { File.join(FIXTURES, 'interesting_files', 'search_replace_db_2') }
10
+
11
+ describe '#url' do
12
+ its(:url) { should eq file }
13
+ end
14
+
15
+ describe '#aggressive' do
16
+ after do
17
+ stub_request(:get, file).to_return(status: status, body: body)
18
+
19
+ expect(finder.aggressive).to eql @expected
20
+ end
21
+
22
+ let(:body) { '' }
23
+
24
+ context 'when 404' do
25
+ let(:status) { 404 }
26
+
27
+ it 'returns nil' do
28
+ @expected = nil
29
+ end
30
+ end
31
+
32
+ context 'when 200' do
33
+ let(:status) { 200 }
34
+
35
+ context 'when the body is empty' do
36
+ it 'returns nil' do
37
+ @expected = nil
38
+ end
39
+ end
40
+
41
+ context 'when the body matches' do
42
+ let(:body) { File.new(File.join(fixtures, 'searchreplacedb2.php')).read }
43
+
44
+ it 'returns the InterestingFile result' do
45
+ @expected = CMSScanner::InterestingFile.new(
46
+ file,
47
+ confidence: 100,
48
+ found_by: 'SearchReplaceDB2 (aggressive detection)'
49
+ )
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ end
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::Finders::InterestingFile::XMLRPC do
4
+
5
+ subject(:finder) { described_class.new(target) }
6
+ let(:target) { CMSScanner::Target.new(url) }
7
+ let(:url) { 'http://ex.lo/' }
8
+ let(:xml_rpc_url) { url + 'xmlrpc.php' }
9
+ let(:fixtures) { File.join(FIXTURES, 'interesting_files', 'xml_rpc') }
10
+
11
+ describe '#potential_urls' do
12
+ its(:potential_urls) { should be_empty }
13
+ end
14
+
15
+ describe '#passive' do
16
+ before do
17
+ expect(finder).to receive(:passive_headers).and_return(headers_stub)
18
+ expect(finder).to receive(:passive_body).and_return(body_stub)
19
+ end
20
+
21
+ context 'when both passives return nil' do
22
+ let(:headers_stub) { nil }
23
+ let(:body_stub) { nil }
24
+
25
+ its(:passive) { should be_empty }
26
+ end
27
+
28
+ context 'when one passive is not nil' do
29
+ let(:headers_stub) { nil }
30
+ let(:body_stub) { 'test' }
31
+
32
+ its(:passive) { should eq %w(test) }
33
+ end
34
+ end
35
+
36
+ describe '#passive_headers' do
37
+ before { stub_request(:get, url).to_return(headers: headers) }
38
+
39
+ let(:headers) { {} }
40
+
41
+ context 'when no headers' do
42
+ its(:passive_headers) { should be_nil }
43
+ end
44
+
45
+ context 'when headers' do
46
+ context 'when URL is out of scope' do
47
+ let(:headers) { { 'X-Pingback' => 'http://ex.org/yolo' } }
48
+
49
+ its(:passive_headers) { should be_nil }
50
+ end
51
+
52
+ context 'when URL is in scope' do
53
+ let(:headers) { { 'X-Pingback' => xml_rpc_url } }
54
+
55
+ it 'adds the url to #potential_urls and returns the XMLRPC' do
56
+ result = finder.passive_headers
57
+
58
+ expect(finder.potential_urls).to eq [xml_rpc_url]
59
+
60
+ expect(result).to be_a CMSScanner::XMLRPC
61
+ expect(result).to eql CMSScanner::XMLRPC.new(
62
+ xml_rpc_url,
63
+ confidence: 30,
64
+ found_by: 'Headers (passive detection)'
65
+ )
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ describe '#passive_body' do
72
+ before { stub_request(:get, url).to_return(body: body) }
73
+
74
+ context 'when no link rel="pingback" tag' do
75
+ let(:body) { '' }
76
+
77
+ its(:passive_body) { should be_nil }
78
+ end
79
+
80
+ context 'when the tag is present' do
81
+ context 'when the URL is out of scope' do
82
+ let(:body) { File.new(File.join(fixtures, 'homepage_out_of_scope_pingback.html')).read }
83
+
84
+ its(:passive_body) { should be_nil }
85
+ end
86
+
87
+ context 'when URL is in scope' do
88
+ let(:body) { File.new(File.join(fixtures, 'homepage_in_scope_pingback.html')).read }
89
+ let(:expected_url) { 'http://ex.lo/wp/xmlrpc.php' }
90
+
91
+ it 'adds the URL to the #potential_urls and returns the XMLRPC' do
92
+ result = finder.passive_body
93
+
94
+ expect(finder.potential_urls).to eq [expected_url]
95
+
96
+ expect(result).to be_a CMSScanner::XMLRPC
97
+ expect(result).to eql CMSScanner::XMLRPC.new(
98
+ expected_url,
99
+ confidence: 30,
100
+ found_by: 'Link Tag (passive detection)'
101
+ )
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ describe '#aggressive' do
108
+ # Adds an out of scope URL which should be ignored
109
+ before { finder.potential_urls << 'htpp://ex.org' }
110
+
111
+ after do
112
+ stub_request(:get, xml_rpc_url).to_return(body: body)
113
+
114
+ expect(finder.aggressive).to eql @expected
115
+ end
116
+
117
+ context 'when the body does not match' do
118
+ let(:body) { '' }
119
+
120
+ it 'returns nil' do
121
+ @expected = nil
122
+ end
123
+ end
124
+
125
+ context 'when the body matches' do
126
+ let(:body) { File.new(File.join(fixtures, 'xmlrpc.php')).read }
127
+
128
+ it 'returns the InterestingFile result' do
129
+ @expected = CMSScanner::XMLRPC.new(
130
+ xml_rpc_url,
131
+ confidence: 100,
132
+ found_by: described_class::DIRECT_FILE_ACCESS
133
+ )
134
+ end
135
+ end
136
+ end
137
+
138
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::Finders::InterestingFiles do
4
+
5
+ it_behaves_like CMSScanner::Finders::IndependentFinder do
6
+ let(:expected_finders) { %w(Headers RobotsTxt FantasticoFileslist SearchReplaceDB2 XMLRPC) }
7
+ end
8
+
9
+ subject(:files) { described_class.new(target) }
10
+ let(:target) { CMSScanner::Target.new(url) }
11
+ let(:url) { 'http://example.com/' }
12
+
13
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::Formatter::CliNoColour do
4
+
5
+ subject(:formatter) { described_class.new }
6
+
7
+ describe '#format' do
8
+ its(:format) { should eq 'cli' }
9
+ end
10
+
11
+ describe '#colorize' do
12
+ it 'returns the text w/o any colour' do
13
+ expect(formatter.red('Text')).to eq 'Text'
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::Formatter::Cli do
4
+
5
+ subject(:formatter) { described_class.new }
6
+
7
+ describe '#format' do
8
+ its(:format) { should eq 'cli' }
9
+ end
10
+
11
+ describe '#green, #red, #colorize' do
12
+ it 'returns the correct red string' do
13
+ expect(formatter.red('Text')).to eq "\e[31mText\e[0m"
14
+ end
15
+
16
+ it 'returns the correct green string' do
17
+ expect(formatter.green('Another Text')).to eq "\e[32mAnother Text\e[0m"
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::Formatter::Json do
4
+
5
+ it_behaves_like CMSScanner::Formatter::Buffer
6
+
7
+ subject(:formatter) { described_class.new }
8
+ let(:output_file) { File.join(FIXTURES, 'output.txt') }
9
+
10
+ before { formatter.views_directories << FIXTURES_VIEWS }
11
+
12
+ describe '#format' do
13
+ its(:format) { should eq 'json' }
14
+ end
15
+
16
+ describe '#output' do
17
+ it 'puts the rendered text in the buffer' do
18
+ 2.times { formatter.output('@render_me', test: 'Working') }
19
+
20
+ expect(formatter.buffer).to eq "\"test\": \"Working\",\n" * 2
21
+ end
22
+ end
23
+
24
+ describe '#beautify' do
25
+ it 'writes the buffer in the file' do
26
+ 2.times { formatter.output('@render_me', test: 'yolo') }
27
+
28
+ expect($stdout).to receive(:puts).with(JSON.pretty_generate(JSON.parse('{"test": "yolo"}')))
29
+ formatter.beautify
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::FantasticoFileslist do
4
+
5
+ subject(:file) { described_class.new(url) }
6
+ let(:url) { 'http://example.com/robots.txt' }
7
+ let(:fixtures) { File.join(FIXTURES, 'interesting_files', 'fantastico_fileslist') }
8
+
9
+ describe '#interesting_entries' do
10
+ let(:headers) { { 'Content-Type' => 'text/plain; charset=utf-8' } }
11
+
12
+ after do
13
+ body = File.new(File.join(fixtures, fixture)).read
14
+
15
+ stub_request(:get, file.url).to_return(headers: headers, body: body)
16
+
17
+ expect(file.interesting_entries).to eq @expected
18
+ end
19
+
20
+ context 'when empty or / entries' do
21
+ let(:fixture) { 'fantastico_fileslist.txt' }
22
+
23
+ it 'ignores them and only returns the others' do
24
+ @expected = %w(data.sql admin.txt)
25
+ end
26
+ end
27
+ end
28
+
29
+ describe '#references' do
30
+ its(:references) { should_not be_nil }
31
+ end
32
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::Headers do
4
+
5
+ subject(:file) { described_class.new(url) }
6
+ let(:url) { 'http://example.com/' }
7
+ let(:fixtures) { File.join(FIXTURES, 'interesting_files', 'headers') }
8
+ let(:fixture) { File.join(fixtures, 'interesting.txt') }
9
+ let(:headers) { {} }
10
+
11
+ before { stub_request(:get, file.url).to_return(headers: headers) }
12
+
13
+ describe '#known_headers' do
14
+ it 'does not contains dupliactes' do
15
+ expect(file.known_headers).to eql file.known_headers.uniq
16
+ end
17
+ end
18
+
19
+ describe '#entries' do
20
+ after { expect(file.entries).to eq @expected if @expected }
21
+
22
+ context 'when no headers' do
23
+ its(:entries) { should eq({}) }
24
+ end
25
+
26
+ context 'when headers' do
27
+ let(:headers) { parse_headers_file(fixture) }
28
+
29
+ it 'returns the headers' do
30
+ @expected = headers
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '#interesting_entries' do
36
+ after { expect(file.interesting_entries).to eq @expected if @expected }
37
+
38
+ context 'when interesting headers' do
39
+ let(:headers) { parse_headers_file(fixture) }
40
+
41
+ it 'returns an array with the headers' do
42
+ @expected = ['Server: nginx/1.1.19', 'X-Article-Id: 12']
43
+ end
44
+ end
45
+
46
+ context 'when no interesting headers' do
47
+ let(:headers) { parse_headers_file(File.join(fixtures, 'no_interesting.txt')) }
48
+
49
+ its(:interesting_entries) { should eq [] }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::InterestingFile do
4
+
5
+ it_behaves_like CMSScanner::Finders::Finding
6
+
7
+ subject(:file) { described_class.new(url, opts) }
8
+ let(:opts) { {} }
9
+ let(:url) { 'http://example.com/' }
10
+ let(:fixtures) { File.join(FIXTURES, 'interesting_files') }
11
+
12
+ describe '#entries' do
13
+ after do
14
+ stub_request(:get, file.url).to_return(headers: headers, body: @body)
15
+
16
+ expect(file.entries).to eq @expected
17
+ end
18
+
19
+ context 'when content-type matches text/plain' do
20
+ let(:headers) { { 'Content-Type' => 'text/plain; charset=utf-8' } }
21
+
22
+ it 'returns the file content as an array w/o empty strings' do
23
+ @body = File.new(File.join(fixtures, 'file.txt')).read
24
+ @expected = ['This is', 'a test file', 'with some content']
25
+ end
26
+ end
27
+
28
+ context 'when other content-type' do
29
+ let(:headers) { { 'Content-Type' => 'text.html; charset=utf-8' } }
30
+
31
+ it 'returns an empty array' do
32
+ @expected = []
33
+ end
34
+ end
35
+ end
36
+
37
+ describe '#==' do
38
+ context 'when same URL' do
39
+ it 'returns true' do
40
+ expect(file == described_class.new(url)).to be true
41
+ end
42
+ end
43
+
44
+ context 'when not the same URL' do
45
+ it 'returns false' do
46
+ expect(file == described_class.new('http://ex.lo')).to be false
47
+ end
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe CMSScanner::RobotsTxt do
4
+
5
+ subject(:file) { described_class.new(url) }
6
+ let(:url) { 'http://example.com/robots.txt' }
7
+ let(:fixtures) { File.join(FIXTURES, 'interesting_files', 'robots_txt') }
8
+
9
+ describe '#interesting_entries' do
10
+ let(:headers) { { 'Content-Type' => 'text/plain; charset=utf-8' } }
11
+
12
+ after do
13
+ body = File.new(File.join(fixtures, fixture)).read
14
+
15
+ stub_request(:get, file.url).to_return(headers: headers, body: body)
16
+
17
+ expect(file.interesting_entries).to eq @expected
18
+ end
19
+
20
+ context 'when empty or / entries' do
21
+ let(:fixture) { 'robots.txt' }
22
+
23
+ it 'ignores them and only returns the others' do
24
+ @expected = %w(/admin /public/home)
25
+ end
26
+ end
27
+ end
28
+ end