codez-tarantula 0.5.0

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 (88) hide show
  1. data/.autotest +14 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG +64 -0
  5. data/DSL_EXAMPLES.md +120 -0
  6. data/Gemfile +2 -0
  7. data/LICENSE +20 -0
  8. data/README.rdoc +136 -0
  9. data/Rakefile +36 -0
  10. data/ci/rails2.gemfile +4 -0
  11. data/ci/rails3.gemfile +4 -0
  12. data/laf/images/header_bg.jpg +0 -0
  13. data/laf/images/logo.png +0 -0
  14. data/laf/images/tagline.png +0 -0
  15. data/laf/javascripts/jquery-1.2.3.js +3408 -0
  16. data/laf/javascripts/jquery-ui-tabs.js +890 -0
  17. data/laf/javascripts/jquery.tablesorter.js +861 -0
  18. data/laf/javascripts/tarantula.js +10 -0
  19. data/laf/stylesheets/tarantula.css +346 -0
  20. data/lib/relevance/core_extensions/ellipsize.rb +38 -0
  21. data/lib/relevance/core_extensions/file.rb +15 -0
  22. data/lib/relevance/core_extensions/metaclass.rb +78 -0
  23. data/lib/relevance/core_extensions/response.rb +14 -0
  24. data/lib/relevance/core_extensions/test_case.rb +21 -0
  25. data/lib/relevance/tarantula.rb +55 -0
  26. data/lib/relevance/tarantula/attack.rb +22 -0
  27. data/lib/relevance/tarantula/attack_handler.rb +43 -0
  28. data/lib/relevance/tarantula/basic_attack.rb +44 -0
  29. data/lib/relevance/tarantula/crawler.rb +271 -0
  30. data/lib/relevance/tarantula/detail.html.erb +81 -0
  31. data/lib/relevance/tarantula/form.rb +29 -0
  32. data/lib/relevance/tarantula/form_submission.rb +98 -0
  33. data/lib/relevance/tarantula/html_document_handler.rb +42 -0
  34. data/lib/relevance/tarantula/html_report_helper.rb +46 -0
  35. data/lib/relevance/tarantula/html_reporter.rb +111 -0
  36. data/lib/relevance/tarantula/index.html.erb +37 -0
  37. data/lib/relevance/tarantula/invalid_html_handler.rb +27 -0
  38. data/lib/relevance/tarantula/io_reporter.rb +40 -0
  39. data/lib/relevance/tarantula/link.rb +105 -0
  40. data/lib/relevance/tarantula/log_grabber.rb +22 -0
  41. data/lib/relevance/tarantula/rails_integration_proxy.rb +90 -0
  42. data/lib/relevance/tarantula/recording.rb +12 -0
  43. data/lib/relevance/tarantula/response.rb +19 -0
  44. data/lib/relevance/tarantula/result.rb +83 -0
  45. data/lib/relevance/tarantula/test_report.html.erb +32 -0
  46. data/lib/relevance/tarantula/tidy_handler.rb +35 -0
  47. data/lib/relevance/tarantula/transform.rb +21 -0
  48. data/lib/relevance/tarantula/version.rb +5 -0
  49. data/lib/relevance/tasks/tarantula_tasks.rake +42 -0
  50. data/lib/tarantula-rails3.rb +9 -0
  51. data/spec/relevance/core_extensions/ellipsize_spec.rb +19 -0
  52. data/spec/relevance/core_extensions/file_spec.rb +7 -0
  53. data/spec/relevance/core_extensions/response_spec.rb +48 -0
  54. data/spec/relevance/core_extensions/test_case_spec.rb +19 -0
  55. data/spec/relevance/tarantula/attack_handler_spec.rb +29 -0
  56. data/spec/relevance/tarantula/basic_attack_spec.rb +12 -0
  57. data/spec/relevance/tarantula/crawler_spec.rb +409 -0
  58. data/spec/relevance/tarantula/form_spec.rb +50 -0
  59. data/spec/relevance/tarantula/form_submission_spec.rb +171 -0
  60. data/spec/relevance/tarantula/html_document_handler_spec.rb +43 -0
  61. data/spec/relevance/tarantula/html_report_helper_spec.rb +46 -0
  62. data/spec/relevance/tarantula/html_reporter_spec.rb +82 -0
  63. data/spec/relevance/tarantula/invalid_html_handler_spec.rb +33 -0
  64. data/spec/relevance/tarantula/io_reporter_spec.rb +11 -0
  65. data/spec/relevance/tarantula/link_spec.rb +132 -0
  66. data/spec/relevance/tarantula/log_grabber_spec.rb +26 -0
  67. data/spec/relevance/tarantula/rails_integration_proxy_spec.rb +100 -0
  68. data/spec/relevance/tarantula/result_spec.rb +85 -0
  69. data/spec/relevance/tarantula/tidy_handler_spec.rb +58 -0
  70. data/spec/relevance/tarantula/transform_spec.rb +20 -0
  71. data/spec/relevance/tarantula_spec.rb +23 -0
  72. data/spec/spec_helper.rb +43 -0
  73. data/tarantula.gemspec +25 -0
  74. data/template/tarantula_test.rb +22 -0
  75. data/vendor/xss-shield/MIT-LICENSE +20 -0
  76. data/vendor/xss-shield/README +76 -0
  77. data/vendor/xss-shield/init.rb +16 -0
  78. data/vendor/xss-shield/lib/xss_shield.rb +6 -0
  79. data/vendor/xss-shield/lib/xss_shield/erb_hacks.rb +111 -0
  80. data/vendor/xss-shield/lib/xss_shield/haml_hacks.rb +42 -0
  81. data/vendor/xss-shield/lib/xss_shield/safe_string.rb +47 -0
  82. data/vendor/xss-shield/lib/xss_shield/secure_helpers.rb +40 -0
  83. data/vendor/xss-shield/test/test_actionview_integration.rb +40 -0
  84. data/vendor/xss-shield/test/test_erb.rb +44 -0
  85. data/vendor/xss-shield/test/test_haml.rb +43 -0
  86. data/vendor/xss-shield/test/test_helpers.rb +25 -0
  87. data/vendor/xss-shield/test/test_safe_string.rb +55 -0
  88. metadata +247 -0
@@ -0,0 +1,50 @@
1
+ require "spec_helper"
2
+
3
+ describe "Relevance::Tarantula::Form large example" do
4
+ before do
5
+ @tag = Hpricot(<<END)
6
+ <form action="/session" method="post">
7
+ <input name="authenticity_token" type="hidden" value="1be0d07c6e13669a87b8f52a3c7e1d1ffa77708d" />
8
+ <input id="email" name="email" size="30" type="text" />
9
+ <input id="password" name="password" size="30" type="password" />
10
+ <input id="remember_me" name="remember_me" type="checkbox" value="1" />
11
+ <input name="commit" type="submit" value="Log in" />
12
+ </form>
13
+ END
14
+ @form = make_form(@tag.at('form'))
15
+ end
16
+
17
+ it "has an action" do
18
+ @form.action.should == "/session"
19
+ end
20
+
21
+ it "has a method" do
22
+ @form.meth.should == "post"
23
+ end
24
+
25
+ end
26
+
27
+ describe "A Relevance::Tarantula::Form" do
28
+ it "defaults method to 'get'" do
29
+ @tag = Hpricot("<form/>")
30
+ @form = make_form(@tag.at('form'))
31
+ @form.meth.should == 'get'
32
+ end
33
+ end
34
+
35
+ describe "A Relevance::Tarantula::Form with a hacked _method" do
36
+ before do
37
+ @tag = Hpricot(<<END)
38
+ <form action="/foo">
39
+ <input name="authenticity_token" type="hidden" value="1be0d07c6e13669a87b8f52a3c7e1d1ffa77708d" />
40
+ <input id="_method" name="_method" size="30" type="text" value="PUT"/>
41
+ </form>
42
+ END
43
+ @form = make_form(@tag.at('form'))
44
+ end
45
+
46
+ it "has a method" do
47
+ @form.meth.should == "put"
48
+ end
49
+
50
+ end
@@ -0,0 +1,171 @@
1
+ require "spec_helper"
2
+
3
+ describe Relevance::Tarantula::FormSubmission do
4
+
5
+ describe "with a good form" do
6
+ # TODO: add more from field types to this example form as needed
7
+ before do
8
+ @tag = Hpricot(%q{
9
+ <form action="/session" method="post">
10
+ <input id="email" name="email" size="30" type="text" />
11
+ <textarea id="comment" name="comment"value="1" />
12
+ <input name="commit" type="submit" value="Postit" />
13
+ <input name="secret" type="hidden" value="secret" />
14
+ <select id="foo_opened_on_1i" name="foo[opened_on(1i)]">
15
+ <option value="2003">2003</option>
16
+ <option value="2004">2004</option>
17
+ </select>
18
+ </form>
19
+ })
20
+ end
21
+
22
+ describe "crawl" do
23
+
24
+ it "converts ActiveRecord::RecordNotFound into a 404" do
25
+ (crawler = stub_everything).expects(:submit).raises(ActiveRecord::RecordNotFound)
26
+ form = Relevance::Tarantula::FormSubmission.new(make_form(@tag.at('form'), crawler))
27
+ response = form.crawl
28
+ response.code.should == "404"
29
+ response.content_type.should == "text/plain"
30
+ response.body.should == "ActiveRecord::RecordNotFound"
31
+ end
32
+
33
+ it "submits the form and logs response" do
34
+ doc = Hpricot('<form action="/action" method="post"/>')
35
+ form = make_form(doc.at('form'))
36
+ fs = Relevance::Tarantula::FormSubmission.new(form)
37
+ form.crawler.expects(:submit).returns(stub(:code => "200"))
38
+ fs.expects(:log).with("Response 200 for #{fs}")
39
+ fs.crawl
40
+ end
41
+
42
+ end
43
+
44
+ describe "with default attack" do
45
+ before do
46
+ @form = make_form(@tag.at('form'))
47
+ @fs = Relevance::Tarantula::FormSubmission.new(@form)
48
+ end
49
+
50
+ it "can mutate text areas" do
51
+ @fs.attack.stubs(:random_int).returns("42")
52
+ @fs.mutate_text_areas(@form).should == {"comment" => "42"}
53
+ end
54
+
55
+ it "can mutate selects" do
56
+ Hpricot::Elements.any_instance.stubs(:sample).returns(stub(:[] => "2006-stub"))
57
+ @fs.mutate_selects(@form).should == {"foo[opened_on(1i)]" => "2006-stub"}
58
+ end
59
+
60
+ it "can mutate inputs" do
61
+ @fs.attack.stubs(:random_int).returns("43")
62
+ @fs.mutate_inputs(@form).should == {"commit"=>"43", "secret"=>"43", "email"=>"43"}
63
+ end
64
+
65
+ it "has a signature based on action and fields" do
66
+ @fs.signature.should == ['/session', [
67
+ "comment",
68
+ "commit",
69
+ "email",
70
+ "foo[opened_on(1i)]",
71
+ "secret"],
72
+ @fs.attack.name]
73
+ end
74
+
75
+ it "has a friendly to_s" do
76
+ @fs.to_s.should =~ %r{^/session post}
77
+ end
78
+ end
79
+
80
+ describe "with a custom attack" do
81
+ before do
82
+ @form = make_form(@tag.at('form'))
83
+ @attack = Relevance::Tarantula::Attack.new(:name => 'foo_name',
84
+ :input => 'foo_code',
85
+ :output => 'foo_code')
86
+ @fs = Relevance::Tarantula::FormSubmission.new(@form, @attack)
87
+ end
88
+
89
+ it "can mutate text areas" do
90
+ @fs.mutate_text_areas(@form).should == {"comment" => "foo_code"}
91
+ end
92
+
93
+ it "can mutate selects" do
94
+ Hpricot::Elements.any_instance.stubs(:sample).returns(stub(:[] => "2006-stub"))
95
+ @fs.mutate_selects(@form).should == {"foo[opened_on(1i)]" => "2006-stub"}
96
+ end
97
+
98
+ it "can mutate inputs" do
99
+ @fs.mutate_inputs(@form).should == {"commit"=>"foo_code", "secret"=>"foo_code", "email"=>"foo_code"}
100
+ end
101
+
102
+ it "has a signature based on action, fields, and attack name" do
103
+ @fs.signature.should == ['/session', [
104
+ "comment",
105
+ "commit",
106
+ "email",
107
+ "foo[opened_on(1i)]",
108
+ "secret"],
109
+ "foo_name"
110
+ ]
111
+ end
112
+
113
+ it "has a friendly to_s" do
114
+ @fs.to_s.should =~ %r{^/session post}
115
+ end
116
+
117
+ it "processes all its attacks" do
118
+ Relevance::Tarantula::FormSubmission.stubs(:attacks).returns([
119
+ Relevance::Tarantula::Attack.new({:name => 'foo_name1', :input => 'foo_input', :output => 'foo_output'}),
120
+ Relevance::Tarantula::Attack.new({:name => 'foo_name2', :input => 'foo_input', :output => 'foo_output'}),
121
+ ])
122
+ Relevance::Tarantula::FormSubmission.mutate(@form).size.should == 2
123
+ end
124
+
125
+ it "maps hash attacks to Attack instances" do
126
+ saved_attacks = Relevance::Tarantula::FormSubmission.instance_variable_get("@attacks")
127
+ begin
128
+ Relevance::Tarantula::FormSubmission.instance_variable_set("@attacks", [{ :name => "attack name"}])
129
+ Relevance::Tarantula::FormSubmission.attacks.should == [Relevance::Tarantula::Attack.new({:name => "attack name"})]
130
+ ensure
131
+ # isolate this test properly
132
+ Relevance::Tarantula::FormSubmission.instance_variable_set("@attacks", saved_attacks)
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ describe "with a crummy form" do
139
+ before do
140
+ @tag = Hpricot(%q{
141
+ <form action="/session" method="post">
142
+ <input value="no_name" />
143
+ </form>
144
+ })
145
+ end
146
+
147
+ describe "with default attack" do
148
+ before do
149
+ @form = make_form(@tag.at('form'))
150
+ @fs = Relevance::Tarantula::FormSubmission.new(@form)
151
+ end
152
+
153
+ it "ignores unnamed inputs" do
154
+ @fs.mutate_inputs(@form).should == {}
155
+ end
156
+ end
157
+
158
+ describe "with a custom attack" do
159
+ before do
160
+ @form = make_form(@tag.at('form'))
161
+ @fs = Relevance::Tarantula::FormSubmission.new(@form, {:name => 'foo_name', :input => 'foo_code', :output => 'foo_code'})
162
+ end
163
+
164
+ it "ignores unnamed inputs" do
165
+ @fs.mutate_inputs(@form).should == {}
166
+ end
167
+ end
168
+
169
+ end
170
+
171
+ end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+
3
+ describe "Relevance::Tarantula::HtmlDocumentHandler" do
4
+
5
+ before do
6
+ @handler = Relevance::Tarantula::HtmlDocumentHandler.new(nil)
7
+ end
8
+
9
+ it "does not write HTML Scanner warnings to the console" do
10
+ bad_html = "<html><div></form></html>"
11
+ err = Recording.stderr do
12
+ @handler.handle(Relevance::Tarantula::Result.new(:response => stub(:html? => true, :body => bad_html)))
13
+ end
14
+ err.should == ""
15
+ end
16
+
17
+ it "ignores non-html" do
18
+ @handler.expects(:queue_link).never
19
+ @handler.handle(Relevance::Tarantula::Result.new(:response => stub(:html? => false, :body => '<a href="/foo">foo</a>')))
20
+ end
21
+
22
+ it "queues anchor tags" do
23
+ @handler.expects(:queue_link).with {|*args| args[0]['href'] == "/foo" && args[1] == nil}
24
+ @handler.handle(Relevance::Tarantula::Result.new(:response => stub(:html? => true, :body => '<a href="/foo">foo</a>')))
25
+ end
26
+
27
+ it "queues link tags" do
28
+ @handler.expects(:queue_link).with {|*args| args[0]['href'] == "/bar" && args[1] == nil}
29
+ @handler.handle(Relevance::Tarantula::Result.new(:response => stub(:html? => true, :body => '<link href="/bar">bar</a>')))
30
+ end
31
+
32
+ it "queues forms" do
33
+ @handler.expects(:queue_form).with{|tag,referrer| Hpricot::Elem === tag}
34
+ @handler.handle(Relevance::Tarantula::Result.new(:url => "/page-url", :response => stub(:html? => true, :body => '<form>stuff</form>')))
35
+ end
36
+
37
+ it "infers form action from page url if form is not explicit" do
38
+ @handler.expects(:queue_form).with{|tag,referrer| tag['action'].should == '/page-url'; true }
39
+ @handler.handle(Relevance::Tarantula::Result.new(:url => "/page-url", :response => stub(:html? => true, :body => '<form>stuff</form>')))
40
+ end
41
+
42
+ end
43
+
@@ -0,0 +1,46 @@
1
+ require "spec_helper"
2
+
3
+ module HtmlReportHelperSpec
4
+ # Is there an idiom for this?
5
+ def self.included(base)
6
+ base.before do
7
+ @reporter = Object.new
8
+ @reporter.extend Relevance::Tarantula::HtmlReportHelper
9
+ end
10
+ end
11
+ end
12
+
13
+ describe 'Relevance::Tarantula::HtmlReportHelper#wrap_in_line_number_table' do
14
+ include HtmlReportHelperSpec
15
+ it "can wrap text in a table row used for displaying lines and line numbers" do
16
+ html = @reporter.wrap_in_line_number_table_row("Line 1\nLine 2")
17
+ html.should == <<-END.strip
18
+ <tr><td class=\"numbers\"><span class=\"line number\">1</span><span class=\"line number\">2</span></td><td class=\"lines\"><span class=\"line\">Line 1</span><span class=\"line\">Line 2</span></td></tr>
19
+ END
20
+ end
21
+ end
22
+
23
+ describe 'Relevance::Tarantula::HtmlReportHelper#wrap_stack_trace_line' do
24
+ include HtmlReportHelperSpec
25
+ it "can wrap stack trace line in links" do
26
+ line = %{/action_controller/filters.rb:697:in `call_filters'}
27
+ @reporter.stubs(:textmate_url).returns("ide_url")
28
+ html = @reporter.wrap_stack_trace_line(line)
29
+ html.should include "<a href='ide_url'>/action_controller/filters.rb:697</a>:in `call_filters"
30
+ end
31
+
32
+ it "converts html entities for non-stack trace lines" do
33
+ line = %{<a href="foo">escape me</a>}
34
+ html = @reporter.wrap_stack_trace_line(line)
35
+ html.should == %{&lt;a href=&quot;foo&quot;&gt;escape me&lt;/a&gt;}
36
+ end
37
+
38
+ end
39
+
40
+ describe 'Relevance::Tarantula::HtmlReportHelper IDE help' do
41
+ include HtmlReportHelperSpec
42
+ it "can create a textmate url" do
43
+ @reporter.stubs(:rails_root).returns("STUB_RAILS_ROOT")
44
+ @reporter.textmate_url("/etc/somewhere", 100).should =~ %r{txmt://open\?url=.*/STUB_RAILS_ROOT/etc/somewhere&line_no=100}
45
+ end
46
+ end
@@ -0,0 +1,82 @@
1
+ require "spec_helper"
2
+
3
+ describe "Relevance::Tarantula::HtmlReporter file output" do
4
+
5
+ before do
6
+ FileUtils.rm_rf(test_output_dir)
7
+ FileUtils.mkdir_p(test_output_dir)
8
+ @test_name = "test_user_pages"
9
+ Relevance::Tarantula::Result.next_number = 0
10
+ @success_results = (1..10).map do |index|
11
+ Relevance::Tarantula::Result.new(
12
+ :success => true,
13
+ :method => "get",
14
+ :url => "/widgets/#{index}",
15
+ :response => stub(:code => "200", :body => "<h1>header</h1>\n<p>text</p>"),
16
+ :referrer => "/random/#{rand(100)}",
17
+ :test_name => @test_name,
18
+ :log => <<-END,
19
+ Made-up stack trace:
20
+ /some_module/some_class.rb:697:in `bad_method'
21
+ /some_module/other_class.rb:12345677:in `long_method'
22
+ this link should be <a href="#">escaped</a>
23
+ blah blah blah
24
+ END
25
+ :data => "{:param1 => :value, :param2 => :another_value}"
26
+ )
27
+ end
28
+ @fail_results = (1..10).map do |index|
29
+ Relevance::Tarantula::Result.new(
30
+ :success => false,
31
+ :method => "get",
32
+ :url => "/widgets/#{index}",
33
+ :response => stub(:code => "500", :body => "<h1>header</h1>\n<p>text</p>"),
34
+ :referrer => "/random/#{rand(100)}",
35
+ :test_name => @test_name,
36
+ :log => <<-END,
37
+ Made-up stack trace:
38
+ /some_module/some_class.rb:697:in `bad_method'
39
+ /some_module/other_class.rb:12345677:in `long_method'
40
+ this link should be <a href="#">escaped</a>
41
+ blah blah blah
42
+ END
43
+ :data => "{:param1 => :value, :param2 => :another_value}"
44
+ )
45
+ end
46
+ @index = File.join(test_output_dir, "index.html")
47
+ FileUtils.rm_f @index
48
+ @detail = File.join(test_output_dir, @test_name,"1.html")
49
+ FileUtils.rm_f @detail
50
+ end
51
+
52
+ it "creates a final report based on tarantula results" do
53
+ Relevance::Tarantula::Result.any_instance.stubs(:rails_root).returns("STUB_ROOT")
54
+ reporter = Relevance::Tarantula::HtmlReporter.new(test_output_dir)
55
+ stub_puts_and_print(reporter)
56
+ (@success_results + @fail_results).each {|r| reporter.report(r)}
57
+ reporter.finish_report(@test_name)
58
+ File.exist?(@index).should be_true
59
+ end
60
+
61
+ it "creates a final report with links to detailed reports in subdirs" do
62
+ Relevance::Tarantula::Result.any_instance.stubs(:rails_root).returns("STUB_ROOT")
63
+ reporter = Relevance::Tarantula::HtmlReporter.new(test_output_dir)
64
+ stub_puts_and_print(reporter)
65
+ (@success_results + @fail_results).each {|r| reporter.report(r)}
66
+ reporter.finish_report(@test_name)
67
+ links = Hpricot(File.read(@index)).search('.left a')
68
+ links.each do |link|
69
+ link['href'].should match(/#{@test_name}\/\d+\.html/)
70
+ end
71
+ end
72
+
73
+ it "creates detailed reports based on tarantula results" do
74
+ Relevance::Tarantula::Result.any_instance.stubs(:rails_root).returns("STUB_ROOT")
75
+ reporter = Relevance::Tarantula::HtmlReporter.new(test_output_dir)
76
+ stub_puts_and_print(reporter)
77
+ (@success_results + @fail_results).each {|r| reporter.report(r)}
78
+ reporter.finish_report(@test_name)
79
+ File.exist?(@detail).should be_true
80
+ end
81
+
82
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+
3
+ describe "Relevance::Tarantula::InvalidHtmlHandler" do
4
+ before do
5
+ @handler = Relevance::Tarantula::InvalidHtmlHandler.new
6
+ end
7
+
8
+ it "does not write HTML Scanner warnings to the console" do
9
+ bad_html = "<html><div></form></html>"
10
+ err = Recording.stderr do
11
+ @handler.handle(Relevance::Tarantula::Result.new(:response => stub(:html? => true, :body => bad_html)))
12
+ end
13
+ err.should == ""
14
+ end
15
+
16
+ it "rejects unclosed html" do
17
+ response = stub(:html? => true, :body => '<html><div></html>', :code => 200)
18
+ result = @handler.handle(Relevance::Tarantula::Result.new(:response => response))
19
+ result.success.should == false
20
+ result.description.should == "Bad HTML (Scanner)"
21
+ end
22
+
23
+ it "loves the good html" do
24
+ response = stub(:html? => true, :body => '<html><div></div></html>', :code => 200)
25
+ @handler.handle(Relevance::Tarantula::Result.new(:response => response)).should == nil
26
+ end
27
+
28
+ it "ignores non html" do
29
+ response = stub(:html? => false, :body => '<html><div></html>', :code => 200)
30
+ @handler.handle(Relevance::Tarantula::Result.new(:response => response)).should == nil
31
+ end
32
+ end
33
+
@@ -0,0 +1,11 @@
1
+ require "spec_helper"
2
+
3
+ describe 'Relevance::Tarantula::IOReporter' do
4
+ it "reports errors to stderr and then raises" do
5
+ reporter = Relevance::Tarantula::IOReporter.new($stderr)
6
+ reporter.report stub(:code => "404", :url => "/uh-oh", :success => false)
7
+ $stderr.expects(:puts).with("****** FAILURES")
8
+ $stderr.expects(:puts).with("404: /uh-oh")
9
+ lambda {reporter.finish_report("test_user_pages")}.should raise_error(RuntimeError)
10
+ end
11
+ end
@@ -0,0 +1,132 @@
1
+ require "spec_helper"
2
+
3
+ describe "Relevance::Tarantula::Link" do
4
+ include ActionView::Helpers::UrlHelper
5
+
6
+ it "does not raise an error when initializing without href attribtue" do
7
+ link = make_link(Hpricot('<a="/foo">foo</a>').at('a'))
8
+ link.href.should == nil
9
+ link.meth.should == 'get'
10
+ end
11
+
12
+ it "parses anchor tags" do
13
+ link = make_link(Hpricot('<a href="/foo">foo</a>').at('a'))
14
+ link.href.should == '/foo'
15
+ link.meth.should == 'get'
16
+ end
17
+
18
+ it "parses anchor tags with POST 'method'" do
19
+ link = make_link(Hpricot(%Q{<a href="/foo" onclick="#{Relevance::Tarantula::Link.method_javascript_function('post')}">foo</a>}).at('a'))
20
+ link.href.should == '/foo'
21
+ link.meth.should == 'post'
22
+ end
23
+
24
+ it "parses anchor tags with POST data-method" do
25
+ link = make_link(Hpricot(%Q{<a href="/foo" data-method="post">foo</a>}).at('a'))
26
+ link.href.should == '/foo'
27
+ link.meth.should == 'post'
28
+ end
29
+
30
+ it "parses anchor tags with POST data-method" do
31
+ link = make_link(Hpricot(%Q{<a href="/foo" data-method="post">foo</a>}).at('a'))
32
+ link.href.should == '/foo'
33
+ link.meth.should == 'post'
34
+ end
35
+
36
+ it "parses anchor tags with PUT 'method'" do
37
+ link = make_link(Hpricot(%Q{<a href="/foo" onclick="#{Relevance::Tarantula::Link.method_javascript_function('put')}">foo</a>}).at('a'))
38
+ link.href.should == '/foo'
39
+ link.meth.should == 'put'
40
+ end
41
+
42
+ it "parses anchor tags with PUT data-method" do
43
+ link = make_link(Hpricot(%Q{<a href="/foo" data-method="put">foo</a>}).at('a'))
44
+ link.href.should == '/foo'
45
+ link.meth.should == 'put'
46
+ end
47
+
48
+ it "parses anchor tags with PATCH data-method" do
49
+ link = make_link(Hpricot(%Q{<a href="/foo" data-method="patch">foo</a>}).at('a'))
50
+ link.href.should == '/foo'
51
+ link.meth.should == 'patch'
52
+ end
53
+
54
+ it "parses anchor tags with PUT data-method" do
55
+ link = make_link(Hpricot(%Q{<a href="/foo" data-method="put">foo</a>}).at('a'))
56
+ link.href.should == '/foo'
57
+ link.meth.should == 'put'
58
+ end
59
+
60
+ it "parses anchor tags with PATCH data-method" do
61
+ link = make_link(Hpricot(%Q{<a href="/foo" data-method="patch">foo</a>}).at('a'))
62
+ link.href.should == '/foo'
63
+ link.meth.should == 'patch'
64
+ end
65
+
66
+ it "parses anchor tags with DELETE 'method'" do
67
+ link = make_link(Hpricot(%Q{<a href="/foo" onclick="#{Relevance::Tarantula::Link.method_javascript_function('delete')}">foo</a>}).at('a'))
68
+ link.href.should == '/foo'
69
+ link.meth.should == 'delete'
70
+ end
71
+
72
+ it "parses anchor tags with DELETE data-method" do
73
+ link = make_link(Hpricot(%Q{<a href="/foo" data-method="delete">foo</a>}).at('a'))
74
+ link.href.should == '/foo'
75
+ link.meth.should == 'delete'
76
+ end
77
+
78
+ it "parses anchor tags with DELETE data-method" do
79
+ link = make_link(Hpricot(%Q{<a href="/foo" data-method="delete">foo</a>}).at('a'))
80
+ link.href.should == '/foo'
81
+ link.meth.should == 'delete'
82
+ end
83
+
84
+ it "parses link tags with text" do
85
+ link = make_link(Hpricot('<link href="/bar">bar</a>').at('link'))
86
+ link.href.should == '/bar'
87
+ link.meth.should == 'get'
88
+ end
89
+
90
+ it "parses link tags without text" do
91
+ link = make_link(Hpricot('<link href="/bar" />').at('link'))
92
+ link.href.should == '/bar'
93
+ link.meth.should == 'get'
94
+ end
95
+
96
+ it 'remembers link referrer if there is one' do
97
+ link = make_link('/url', stub_everything, '/some-referrer')
98
+ link.referrer.should == '/some-referrer'
99
+ end
100
+
101
+ it "does two things when crawled: follow, log, and handle" do
102
+ crawler = Relevance::Tarantula::Crawler.new
103
+ link = make_link('/foo', crawler)
104
+
105
+ response = stub(:code => "200")
106
+ crawler.expects(:follow).returns(response)
107
+ link.expects(:log)
108
+ crawler.expects(:handle_link_results)
109
+
110
+ link.crawl
111
+ end
112
+
113
+ # method_javascript_function needs this method
114
+ def protect_against_forgery?
115
+ false
116
+ end
117
+
118
+ end
119
+
120
+ describe "possible conflict when user has an AR model named Link" do
121
+ it "does not taint Object with Relevance::Tarantula" do
122
+ Object.ancestors.should_not include(Relevance::Tarantula)
123
+ end
124
+
125
+ it "doesnt break with a Link model" do
126
+ lambda {
127
+ class Link < ActiveRecord::Base
128
+ end
129
+ }.should_not raise_error
130
+ end
131
+
132
+ end