panmind-tarantula 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/CHANGELOG +49 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +171 -0
  4. data/Rakefile +83 -0
  5. data/VERSION.yml +4 -0
  6. data/examples/example_helper.rb +57 -0
  7. data/examples/relevance/core_extensions/ellipsize_example.rb +19 -0
  8. data/examples/relevance/core_extensions/file_example.rb +8 -0
  9. data/examples/relevance/core_extensions/response_example.rb +29 -0
  10. data/examples/relevance/core_extensions/test_case_example.rb +20 -0
  11. data/examples/relevance/tarantula/attack_handler_example.rb +29 -0
  12. data/examples/relevance/tarantula/basic_attack_example.rb +12 -0
  13. data/examples/relevance/tarantula/crawler_example.rb +375 -0
  14. data/examples/relevance/tarantula/form_example.rb +50 -0
  15. data/examples/relevance/tarantula/form_submission_example.rb +171 -0
  16. data/examples/relevance/tarantula/html_document_handler_example.rb +43 -0
  17. data/examples/relevance/tarantula/html_report_helper_example.rb +46 -0
  18. data/examples/relevance/tarantula/html_reporter_example.rb +82 -0
  19. data/examples/relevance/tarantula/invalid_html_handler_example.rb +33 -0
  20. data/examples/relevance/tarantula/io_reporter_example.rb +11 -0
  21. data/examples/relevance/tarantula/link_example.rb +84 -0
  22. data/examples/relevance/tarantula/log_grabber_example.rb +26 -0
  23. data/examples/relevance/tarantula/rails_integration_proxy_example.rb +101 -0
  24. data/examples/relevance/tarantula/result_example.rb +85 -0
  25. data/examples/relevance/tarantula/tidy_handler_example.rb +58 -0
  26. data/examples/relevance/tarantula/transform_example.rb +20 -0
  27. data/examples/relevance/tarantula_example.rb +23 -0
  28. data/laf/images/header_bg.jpg +0 -0
  29. data/laf/images/logo.png +0 -0
  30. data/laf/images/tagline.png +0 -0
  31. data/laf/javascripts/jquery-1.2.3.js +3408 -0
  32. data/laf/javascripts/jquery-ui-tabs.js +890 -0
  33. data/laf/javascripts/jquery.tablesorter.js +861 -0
  34. data/laf/javascripts/tarantula.js +10 -0
  35. data/laf/stylesheets/tarantula.css +346 -0
  36. data/lib/relevance/core_extensions/ellipsize.rb +34 -0
  37. data/lib/relevance/core_extensions/file.rb +9 -0
  38. data/lib/relevance/core_extensions/metaclass.rb +78 -0
  39. data/lib/relevance/core_extensions/response.rb +9 -0
  40. data/lib/relevance/core_extensions/string_chars_fix.rb +11 -0
  41. data/lib/relevance/core_extensions/test_case.rb +19 -0
  42. data/lib/relevance/tarantula.rb +59 -0
  43. data/lib/relevance/tarantula/attack.rb +18 -0
  44. data/lib/relevance/tarantula/attack_handler.rb +37 -0
  45. data/lib/relevance/tarantula/basic_attack.rb +40 -0
  46. data/lib/relevance/tarantula/crawler.rb +254 -0
  47. data/lib/relevance/tarantula/detail.html.erb +81 -0
  48. data/lib/relevance/tarantula/form.rb +23 -0
  49. data/lib/relevance/tarantula/form_submission.rb +88 -0
  50. data/lib/relevance/tarantula/html_document_handler.rb +36 -0
  51. data/lib/relevance/tarantula/html_report_helper.rb +39 -0
  52. data/lib/relevance/tarantula/html_reporter.rb +105 -0
  53. data/lib/relevance/tarantula/index.html.erb +37 -0
  54. data/lib/relevance/tarantula/invalid_html_handler.rb +18 -0
  55. data/lib/relevance/tarantula/io_reporter.rb +34 -0
  56. data/lib/relevance/tarantula/link.rb +76 -0
  57. data/lib/relevance/tarantula/log_grabber.rb +16 -0
  58. data/lib/relevance/tarantula/rails_integration_proxy.rb +87 -0
  59. data/lib/relevance/tarantula/recording.rb +12 -0
  60. data/lib/relevance/tarantula/response.rb +13 -0
  61. data/lib/relevance/tarantula/result.rb +77 -0
  62. data/lib/relevance/tarantula/test_report.html.erb +32 -0
  63. data/lib/relevance/tarantula/tidy_handler.rb +32 -0
  64. data/lib/relevance/tarantula/transform.rb +17 -0
  65. data/tasks/tarantula_tasks.rake +42 -0
  66. data/template/tarantula_test.rb +22 -0
  67. metadata +213 -0
@@ -0,0 +1,171 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "example_helper.rb"))
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(:rand).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(:rand).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 File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "example_helper.rb"))
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 File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "example_helper.rb"))
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 == "<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 File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "example_helper.rb"))
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 File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "example_helper.rb"))
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 File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "example_helper.rb"))
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,84 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "example_helper.rb"))
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.method.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.method.should == :get
16
+ end
17
+
18
+ it "parses anchor tags with POST 'method'" do
19
+ link = make_link(Hpricot(%Q{<a href="/foo" onclick="#{method_javascript_function(:post)}">foo</a>}).at('a'))
20
+ link.href.should == '/foo'
21
+ link.method.should == :post
22
+ end
23
+
24
+ it "parses anchor tags with PUT 'method'" do
25
+ link = make_link(Hpricot(%Q{<a href="/foo" onclick="#{method_javascript_function(:put)}">foo</a>}).at('a'))
26
+ link.href.should == '/foo'
27
+ link.method.should == :put
28
+ end
29
+
30
+ it "parses anchor tags with DELETE 'method'" do
31
+ link = make_link(Hpricot(%Q{<a href="/foo" onclick="#{method_javascript_function(:delete)}">foo</a>}).at('a'))
32
+ link.href.should == '/foo'
33
+ link.method.should == :delete
34
+ end
35
+
36
+ it "parses link tags with text" do
37
+ link = make_link(Hpricot('<link href="/bar">bar</a>').at('link'))
38
+ link.href.should == '/bar'
39
+ link.method.should == :get
40
+ end
41
+
42
+ it "parses link tags without text" do
43
+ link = make_link(Hpricot('<link href="/bar" />').at('link'))
44
+ link.href.should == '/bar'
45
+ link.method.should == :get
46
+ end
47
+
48
+ it 'remembers link referrer if there is one' do
49
+ link = make_link('/url', stub_everything, '/some-referrer')
50
+ link.referrer.should == '/some-referrer'
51
+ end
52
+
53
+ it "does two things when crawled: follow, log, and handle" do
54
+ crawler = Relevance::Tarantula::Crawler.new
55
+ link = make_link('/foo', crawler)
56
+
57
+ response = stub(:code => "200")
58
+ crawler.expects(:follow).returns(response)
59
+ link.expects(:log)
60
+ crawler.expects(:handle_link_results)
61
+
62
+ link.crawl
63
+ end
64
+
65
+ # method_javascript_function needs this method
66
+ def protect_against_forgery?
67
+ false
68
+ end
69
+
70
+ end
71
+
72
+ describe "possible conflict when user has an AR model named Link" do
73
+ it "does not taint Object with Relevance::Tarantula" do
74
+ Object.ancestors.should_not include(Relevance::Tarantula)
75
+ end
76
+
77
+ it "doesnt break with a Link model" do
78
+ lambda {
79
+ class Link < ActiveRecord::Base
80
+ end
81
+ }.should_not raise_error
82
+ end
83
+
84
+ end