tarantula 0.0.5
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.
- data/CHANGELOG +2 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +106 -0
- data/Rakefile +80 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/laf/images/background.jpg +0 -0
- data/laf/images/relevance-os-logo.gif +0 -0
- data/laf/images/tab.png +0 -0
- data/laf/images/table-sort.gif +0 -0
- data/laf/images/tarantula-sprites.png +0 -0
- data/laf/javascripts/jquery-1.2.3.js +3408 -0
- data/laf/javascripts/jquery-ui-tabs.js +890 -0
- data/laf/javascripts/jquery.tablesorter.js +861 -0
- data/laf/javascripts/tarantula.js +10 -0
- data/laf/stylesheets/tarantula.css +638 -0
- data/laf/stylesheets/ui.tabs.css +113 -0
- data/lib/relevance/core_extensions/ellipsize.rb +34 -0
- data/lib/relevance/core_extensions/file.rb +9 -0
- data/lib/relevance/core_extensions/response.rb +9 -0
- data/lib/relevance/core_extensions/test_case.rb +12 -0
- data/lib/relevance/tarantula.rb +63 -0
- data/lib/relevance/tarantula/attack.rb +15 -0
- data/lib/relevance/tarantula/attack_form_submission.rb +75 -0
- data/lib/relevance/tarantula/attack_handler.rb +37 -0
- data/lib/relevance/tarantula/crawler.rb +240 -0
- data/lib/relevance/tarantula/detail.html.erb +77 -0
- data/lib/relevance/tarantula/form.rb +21 -0
- data/lib/relevance/tarantula/form_submission.rb +70 -0
- data/lib/relevance/tarantula/html_document_handler.rb +36 -0
- data/lib/relevance/tarantula/html_report_helper.rb +56 -0
- data/lib/relevance/tarantula/html_reporter.rb +105 -0
- data/lib/relevance/tarantula/index.html.erb +48 -0
- data/lib/relevance/tarantula/invalid_html_handler.rb +18 -0
- data/lib/relevance/tarantula/io_reporter.rb +34 -0
- data/lib/relevance/tarantula/link.rb +56 -0
- data/lib/relevance/tarantula/log_grabber.rb +16 -0
- data/lib/relevance/tarantula/rails_integration_proxy.rb +70 -0
- data/lib/relevance/tarantula/recording.rb +12 -0
- data/lib/relevance/tarantula/response.rb +13 -0
- data/lib/relevance/tarantula/result.rb +66 -0
- data/lib/relevance/tarantula/test_report.html.erb +34 -0
- data/lib/relevance/tarantula/tidy_handler.rb +32 -0
- data/lib/relevance/tarantula/transform.rb +17 -0
- data/manifest.txt +117 -0
- data/rails/init.rb +1 -0
- data/tarantula.gemspec +48 -0
- data/tasks/tarantula_tasks.rake +34 -0
- data/template/tarantula_test.rb +12 -0
- data/test/relevance/core_extensions/ellipsize_test.rb +19 -0
- data/test/relevance/core_extensions/file_test.rb +8 -0
- data/test/relevance/core_extensions/response_test.rb +29 -0
- data/test/relevance/core_extensions/test_case_test.rb +16 -0
- data/test/relevance/tarantula/attack_form_submission_test.rb +79 -0
- data/test/relevance/tarantula/attack_handler_test.rb +29 -0
- data/test/relevance/tarantula/crawler_test.rb +296 -0
- data/test/relevance/tarantula/form_submission_test.rb +71 -0
- data/test/relevance/tarantula/form_test.rb +50 -0
- data/test/relevance/tarantula/html_document_handler_test.rb +43 -0
- data/test/relevance/tarantula/html_report_helper_test.rb +47 -0
- data/test/relevance/tarantula/html_reporter_test.rb +82 -0
- data/test/relevance/tarantula/invalid_html_handler_test.rb +33 -0
- data/test/relevance/tarantula/io_reporter_test.rb +11 -0
- data/test/relevance/tarantula/link_test.rb +61 -0
- data/test/relevance/tarantula/log_grabber_test.rb +26 -0
- data/test/relevance/tarantula/rails_integration_proxy_test.rb +94 -0
- data/test/relevance/tarantula/result_test.rb +85 -0
- data/test/relevance/tarantula/tidy_handler_test.rb +58 -0
- data/test/relevance/tarantula/transform_test.rb +21 -0
- data/test/relevance/tarantula_test.rb +23 -0
- data/test/test_helper.rb +34 -0
- data/tmp/test_output/images/background.jpg +0 -0
- data/tmp/test_output/images/relevance-os-logo.gif +0 -0
- data/tmp/test_output/images/tab.png +0 -0
- data/tmp/test_output/images/table-sort.gif +0 -0
- data/tmp/test_output/images/tarantula-sprites.png +0 -0
- data/tmp/test_output/index.html +255 -0
- data/tmp/test_output/javascripts/jquery-1.2.3.js +3408 -0
- data/tmp/test_output/javascripts/jquery-ui-tabs.js +890 -0
- data/tmp/test_output/javascripts/jquery.tablesorter.js +861 -0
- data/tmp/test_output/javascripts/tarantula.js +10 -0
- data/tmp/test_output/stylesheets/tarantula.css +638 -0
- data/tmp/test_output/stylesheets/ui.tabs.css +113 -0
- data/tmp/test_output/test_user_pages/1.html +71 -0
- data/tmp/test_output/test_user_pages/10.html +71 -0
- data/tmp/test_output/test_user_pages/11.html +71 -0
- data/tmp/test_output/test_user_pages/12.html +71 -0
- data/tmp/test_output/test_user_pages/13.html +71 -0
- data/tmp/test_output/test_user_pages/14.html +71 -0
- data/tmp/test_output/test_user_pages/15.html +71 -0
- data/tmp/test_output/test_user_pages/16.html +71 -0
- data/tmp/test_output/test_user_pages/17.html +71 -0
- data/tmp/test_output/test_user_pages/18.html +71 -0
- data/tmp/test_output/test_user_pages/19.html +71 -0
- data/tmp/test_output/test_user_pages/2.html +71 -0
- data/tmp/test_output/test_user_pages/20.html +71 -0
- data/tmp/test_output/test_user_pages/3.html +71 -0
- data/tmp/test_output/test_user_pages/4.html +71 -0
- data/tmp/test_output/test_user_pages/5.html +71 -0
- data/tmp/test_output/test_user_pages/6.html +71 -0
- data/tmp/test_output/test_user_pages/7.html +71 -0
- data/tmp/test_output/test_user_pages/8.html +71 -0
- data/tmp/test_output/test_user_pages/9.html +71 -0
- data/uninstall.rb +1 -0
- data/vendor/xss-shield/MIT-LICENSE +20 -0
- data/vendor/xss-shield/README +76 -0
- data/vendor/xss-shield/init.rb +16 -0
- data/vendor/xss-shield/lib/xss_shield.rb +6 -0
- data/vendor/xss-shield/lib/xss_shield/erb_hacks.rb +111 -0
- data/vendor/xss-shield/lib/xss_shield/haml_hacks.rb +42 -0
- data/vendor/xss-shield/lib/xss_shield/safe_string.rb +47 -0
- data/vendor/xss-shield/lib/xss_shield/secure_helpers.rb +40 -0
- data/vendor/xss-shield/test/test_actionview_integration.rb +40 -0
- data/vendor/xss-shield/test/test_erb.rb +44 -0
- data/vendor/xss-shield/test/test_haml.rb +43 -0
- data/vendor/xss-shield/test/test_helpers.rb +25 -0
- data/vendor/xss-shield/test/test_safe_string.rb +55 -0
- metadata +283 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "test_helper.rb")
|
|
2
|
+
|
|
3
|
+
describe "Relevance::Tarantula::FormSubmission" do
|
|
4
|
+
|
|
5
|
+
# TODO: add more from field types to this example form as needed
|
|
6
|
+
before do
|
|
7
|
+
@tag = Hpricot(<<END)
|
|
8
|
+
<form action="/session" method="post">
|
|
9
|
+
<input id="email" name="email" size="30" type="text" />
|
|
10
|
+
<textarea id="comment" name="comment"value="1" />
|
|
11
|
+
<input name="commit" type="submit" value="Postit" />
|
|
12
|
+
<input name="secret" type="hidden" value="secret" />
|
|
13
|
+
<select id="foo_opened_on_1i" name="foo[opened_on(1i)]">
|
|
14
|
+
<option value="2003">2003</option>
|
|
15
|
+
<option value="2004">2004</option>
|
|
16
|
+
</select>
|
|
17
|
+
</form>
|
|
18
|
+
END
|
|
19
|
+
@form = Relevance::Tarantula::Form.new(@tag.at('form'))
|
|
20
|
+
@fs = Relevance::Tarantula::FormSubmission.new(@form)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "can mutate text areas" do
|
|
24
|
+
@fs.stubs(:random_int).returns("42")
|
|
25
|
+
@fs.mutate_text_areas(@form).should == {"comment" => "42"}
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "can mutate selects" do
|
|
29
|
+
Hpricot::Elements.any_instance.stubs(:rand).returns(stub(:[] => "2006-stub"))
|
|
30
|
+
@fs.mutate_selects(@form).should == {"foo[opened_on(1i)]" => "2006-stub"}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "can mutate inputs" do
|
|
34
|
+
@fs.stubs(:random_int).returns("43")
|
|
35
|
+
@fs.mutate_inputs(@form).should == {"commit"=>"43", "secret"=>"43", "email"=>"43"}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "has a signature based on action and fields" do
|
|
39
|
+
@fs.signature.should == ['/session', [
|
|
40
|
+
"comment",
|
|
41
|
+
"commit",
|
|
42
|
+
"email",
|
|
43
|
+
"foo[opened_on(1i)]",
|
|
44
|
+
"secret"]]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "has a friendly to_s" do
|
|
48
|
+
@fs.to_s.should =~ %r{^/session post}
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "can generate a random whole number" do
|
|
52
|
+
@fs.random_whole_number.should >= 0
|
|
53
|
+
Fixnum.should === @fs.random_whole_number
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "Relevance::Tarantula::FormSubmission for a crummy form" do
|
|
58
|
+
before do
|
|
59
|
+
@tag = Hpricot(<<END)
|
|
60
|
+
<form action="/session" method="post">
|
|
61
|
+
<input value="no_name" />
|
|
62
|
+
</form>
|
|
63
|
+
END
|
|
64
|
+
@form = Relevance::Tarantula::Form.new(@tag.at('form'))
|
|
65
|
+
@fs = Relevance::Tarantula::FormSubmission.new(@form)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "ignores unnamed inputs" do
|
|
69
|
+
@fs.mutate_inputs(@form).should == {}
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "test_helper.rb")
|
|
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 = Relevance::Tarantula::Form.new(@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.method.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 = Relevance::Tarantula::Form.new(@tag.at('form'))
|
|
31
|
+
@form.method.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 = Relevance::Tarantula::Form.new(@tag.at('form'))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "has a method" do
|
|
47
|
+
@form.method.should == "put"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "test_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,47 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "test_helper.rb")
|
|
2
|
+
|
|
3
|
+
module HtmlReportHelperSpec
|
|
4
|
+
|
|
5
|
+
# Is there an idiom for this?
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.before do
|
|
8
|
+
@reporter = Object.new
|
|
9
|
+
@reporter.extend Relevance::Tarantula::HtmlReportHelper
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe 'Relevance::Tarantula::HtmlReportHelper#wrap_in_line_number_table' do
|
|
15
|
+
include HtmlReportHelperSpec
|
|
16
|
+
it "can wrap text in a line number table" do
|
|
17
|
+
html = @reporter.wrap_in_line_number_table("Line 1\nLine 2")
|
|
18
|
+
html.should == <<-END.strip
|
|
19
|
+
<table class="grid tablesorter"><thead><tr><th class="sort asc"><span>Line #</span><span class="sort"><em>↥</em></span></th><th class="sort left"><span>Line</span><span class="sort"><em>↥</em></span></th></tr></thead><tr><td>1</td><td>Line 1</td></tr><tr><td>2</td><td>Line 2</td></tr></table>
|
|
20
|
+
END
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe 'Relevance::Tarantula::HtmlReportHelper#wrap_stack_trace_line' do
|
|
25
|
+
include HtmlReportHelperSpec
|
|
26
|
+
it "can wrap stack trace line in links" do
|
|
27
|
+
line = %{/action_controller/filters.rb:697:in `call_filters'}
|
|
28
|
+
@reporter.stubs(:textmate_url).returns("ide_url")
|
|
29
|
+
html = @reporter.wrap_stack_trace_line(line)
|
|
30
|
+
html.should == "<a href='ide_url'>/action_controller/filters.rb:697</a>:in `call_filters'"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "converts html entities for non-stack trace lines" do
|
|
34
|
+
line = %{<a href="foo">escape me</a>}
|
|
35
|
+
html = @reporter.wrap_stack_trace_line(line)
|
|
36
|
+
html.should == %{<a href="foo">escape me</a>}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe 'Relevance::Tarantula::HtmlReportHelper IDE help' do
|
|
42
|
+
include HtmlReportHelperSpec
|
|
43
|
+
it "can create a textmate url" do
|
|
44
|
+
@reporter.stubs(:rails_root).returns("STUB_RAILS_ROOT")
|
|
45
|
+
@reporter.textmate_url("/etc/somewhere", 100).should =~ %r{txmt://open\?url=.*/STUB_RAILS_ROOT/etc/somewhere&line_no=100}
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "test_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.should.exist @index
|
|
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.should.exist @detail
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "test_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.join(File.dirname(__FILE__), "..", "..", "test_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 RuntimeError
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "test_helper.rb")
|
|
2
|
+
|
|
3
|
+
describe "Relevance::Tarantula::Link" do
|
|
4
|
+
include ActionView::Helpers::UrlHelper
|
|
5
|
+
|
|
6
|
+
it "parses anchor tags" do
|
|
7
|
+
link = Relevance::Tarantula::Link.new(Hpricot('<a href="/foo">foo</a>').at('a'))
|
|
8
|
+
assert_equal "/foo", link.href
|
|
9
|
+
assert_equal :get, link.method
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "parses anchor tags with POST 'method'" do
|
|
13
|
+
link = Relevance::Tarantula::Link.new(Hpricot(%Q{<a href="/foo" onclick="#{method_javascript_function(:post)}">foo</a>}).at('a'))
|
|
14
|
+
assert_equal "/foo", link.href
|
|
15
|
+
assert_equal :post, link.method
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "parses anchor tags with PUT 'method'" do
|
|
19
|
+
link = Relevance::Tarantula::Link.new(Hpricot(%Q{<a href="/foo" onclick="#{method_javascript_function(:put)}">foo</a>}).at('a'))
|
|
20
|
+
assert_equal "/foo", link.href
|
|
21
|
+
assert_equal :put, link.method
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "parses anchor tags with DELETE 'method'" do
|
|
25
|
+
link = Relevance::Tarantula::Link.new(Hpricot(%Q{<a href="/foo" onclick="#{method_javascript_function(:delete)}">foo</a>}).at('a'))
|
|
26
|
+
assert_equal "/foo", link.href
|
|
27
|
+
assert_equal :delete, link.method
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "parses link tags with text" do
|
|
31
|
+
link = Relevance::Tarantula::Link.new(Hpricot('<link href="/bar">bar</a>').at('link'))
|
|
32
|
+
assert_equal "/bar", link.href
|
|
33
|
+
assert_equal :get, link.method
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "parses link tags without text" do
|
|
37
|
+
link = Relevance::Tarantula::Link.new(Hpricot('<link href="/bar" />').at('link'))
|
|
38
|
+
assert_equal "/bar", link.href
|
|
39
|
+
assert_equal :get, link.method
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# method_javascript_function needs this method
|
|
43
|
+
def protect_against_forgery?
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "possible conflict when user has an AR model named Link" do
|
|
50
|
+
it "does not taint Object with Relevance::Tarantula" do
|
|
51
|
+
Object.ancestors.should.not.include Relevance::Tarantula
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "doesnt break with a Link model" do
|
|
55
|
+
lambda {
|
|
56
|
+
class Link < ActiveRecord::Base
|
|
57
|
+
end
|
|
58
|
+
}.should.not.raise
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "test_helper.rb")
|
|
2
|
+
|
|
3
|
+
describe 'Relevance::Tarantula::LogGrabber' do
|
|
4
|
+
before do
|
|
5
|
+
@grabber = Relevance::Tarantula::LogGrabber.new(log_file)
|
|
6
|
+
FileUtils.mkdir_p(test_output_dir)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def log_file
|
|
10
|
+
File.join(File.join(test_output_dir, "example.log"))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "can clear the log file" do
|
|
14
|
+
File.open(log_file, "w") {|f| f.print "sample log"}
|
|
15
|
+
File.size(log_file).should == 10
|
|
16
|
+
@grabber.clear!
|
|
17
|
+
File.size(log_file).should == 0
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "can grab the log file" do
|
|
21
|
+
File.open(log_file, "w") {|f| f.print "sample log"}
|
|
22
|
+
@grabber.grab!.should == "sample log"
|
|
23
|
+
File.size(log_file).should == 0
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "test_helper.rb")
|
|
2
|
+
|
|
3
|
+
describe "Relevance::Tarantula::RailsIntegrationProxy rails_integration_test" do
|
|
4
|
+
before {
|
|
5
|
+
Relevance::Tarantula::Crawler.any_instance.stubs(:crawl)
|
|
6
|
+
Relevance::Tarantula::Crawler.any_instance.stubs(:rails_root).returns("STUB_RAILS_ROOT")
|
|
7
|
+
Relevance::Tarantula::RailsIntegrationProxy.stubs(:rails_root).returns("STUB_RAILS_ROOT")
|
|
8
|
+
Relevance::Tarantula::RailsIntegrationProxy.stubs(:new).returns(stub(:integration_test => stub(:method_name => @test_name)))
|
|
9
|
+
@test_name = "test_user_pages"
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
it "strips leading hostname from link urls" do
|
|
13
|
+
crawler = Relevance::Tarantula::RailsIntegrationProxy.rails_integration_test(stub(:host => "foo.com"))
|
|
14
|
+
crawler.transform_url("http://foo.com/path").should == "/path"
|
|
15
|
+
crawler.transform_url("http://bar.com/path").should == "http://bar.com/path"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "allows override of max_url_length" do
|
|
19
|
+
crawler = Relevance::Tarantula::RailsIntegrationProxy.rails_integration_test(stub(:host => "foo.com"),
|
|
20
|
+
:max_url_length => 16)
|
|
21
|
+
crawler.max_url_length.should == 16
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "has some useful defaults" do
|
|
25
|
+
crawler = Relevance::Tarantula::RailsIntegrationProxy.rails_integration_test(stub(:host => "foo.com"))
|
|
26
|
+
crawler.log_grabber.should.not.be nil
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
describe "Relevance::Tarantula::RailsIntegrationProxy" do
|
|
32
|
+
%w{get post}.each do |http_method|
|
|
33
|
+
it "can #{http_method}" do
|
|
34
|
+
@rip = Relevance::Tarantula::RailsIntegrationProxy.new(stub)
|
|
35
|
+
@response = stub({:code => :foo})
|
|
36
|
+
@rip.integration_test = stub_everything(:response => @response)
|
|
37
|
+
@rip.send(http_method, "/url").should.be @response
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "adds a response accessor to its delegate rails integration test" do
|
|
42
|
+
o = Object.new
|
|
43
|
+
Relevance::Tarantula::RailsIntegrationProxy.new(o)
|
|
44
|
+
o.methods(false).sort.should == %w{response response=}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "Relevance::Tarantula::RailsIntegrationProxy patching" do
|
|
50
|
+
before do
|
|
51
|
+
@rip = Relevance::Tarantula::RailsIntegrationProxy.new(stub)
|
|
52
|
+
@rip.stubs(:rails_root).returns("faux_rails_root")
|
|
53
|
+
@response = stub_everything({:code => "404", :headers => {}})
|
|
54
|
+
File.stubs(:exist?).returns(true)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "patches in Relevance::CoreExtensions::Response" do
|
|
58
|
+
@rip = Relevance::Tarantula::RailsIntegrationProxy.new(stub)
|
|
59
|
+
@rip.stubs(:rails_root).returns("faux_rails_root")
|
|
60
|
+
@response = stub_everything({:code => "404", :headers => {}, :content_type => "text/html"})
|
|
61
|
+
@response.meta.ancestors.should.not.include Relevance::CoreExtensions::Response
|
|
62
|
+
@rip.patch_response("/url", @response)
|
|
63
|
+
@response.meta.ancestors.should.include Relevance::CoreExtensions::Response
|
|
64
|
+
@response.html?.should == true
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "ignores 404s for known static binary types" do
|
|
68
|
+
File.expects(:extension).returns("pdf")
|
|
69
|
+
@rip.expects(:log).with("Skipping /url (for now)")
|
|
70
|
+
@rip.patch_response("/url", @response)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "replaces 404s with 200s, pulling content from public, for known text types" do
|
|
74
|
+
File.expects(:extension).returns("html")
|
|
75
|
+
@rip.expects(:static_content_file).with("/url").returns("File body")
|
|
76
|
+
@rip.patch_response("/url", @response)
|
|
77
|
+
@response.headers.should == {"type" => "text/html"}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "logs and skips types we haven't dealt with yet" do
|
|
81
|
+
File.expects(:extension).returns("whizzy")
|
|
82
|
+
@rip.expects(:log).with("Skipping unknown type /url")
|
|
83
|
+
@rip.patch_response("/url", @response)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "can find static content relative to rails root" do
|
|
87
|
+
@rip.static_content_path("foo").should == File.expand_path("faux_rails_root/public/foo")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "can read static content relative to rails root" do
|
|
91
|
+
File.expects(:read).with(@rip.static_content_path("foo"))
|
|
92
|
+
@rip.static_content_file("foo")
|
|
93
|
+
end
|
|
94
|
+
end
|