panmind-tarantula 0.3.3

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 (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,76 @@
1
+ class Relevance::Tarantula::Link
2
+ include Relevance::Tarantula
3
+
4
+ class << self
5
+ include ActionView::Helpers::UrlHelper
6
+ # method_javascript_function needs this method
7
+ def protect_against_forgery?
8
+ false
9
+ end
10
+ end
11
+
12
+ METHOD_REGEXPS = {}
13
+ [:put, :delete, :post].each do |m|
14
+ # remove submit from the end so we'll match with or without forgery protection
15
+ s = method_javascript_function(m).gsub( /f.submit();/, "" )
16
+ # don't just match this.href in case a different url was passed originally
17
+ s = Regexp.escape(s).gsub( /this.href/, ".*" )
18
+ METHOD_REGEXPS[m] = /#{s}/
19
+ end
20
+
21
+ attr_accessor :href, :crawler, :referrer
22
+
23
+ def initialize(link, crawler, referrer)
24
+ @crawler, @referrer = crawler, referrer
25
+
26
+ if String === link || link.nil?
27
+ @href = transform_url(link)
28
+ @method = :get
29
+ else # should be a tag
30
+ @href = link['href'] ? transform_url(link['href'].downcase) : nil
31
+ @tag = link
32
+ end
33
+ end
34
+
35
+ def crawl
36
+ response = crawler.follow(method, href)
37
+ log "Response #{response.code} for #{self}"
38
+ crawler.handle_link_results(self, make_result(response))
39
+ end
40
+
41
+ def make_result(response)
42
+ crawler.make_result(:method => method,
43
+ :url => href,
44
+ :response => response,
45
+ :referrer => referrer)
46
+ end
47
+
48
+ def method
49
+ @method ||= begin
50
+ (@tag &&
51
+ [:put, :delete, :post].detect do |m| # post should be last since it's least specific
52
+ @tag['onclick'] =~ METHOD_REGEXPS[m]
53
+ end) ||
54
+ :get
55
+ end
56
+ end
57
+
58
+ def transform_url(link)
59
+ crawler.transform_url(link)
60
+ end
61
+
62
+ def ==(obj)
63
+ obj.respond_to?(:href) && obj.respond_to?(:method) &&
64
+ self.href.to_s == obj.href.to_s && self.method.to_s == obj.method.to_s
65
+ end
66
+ alias :eql? :==
67
+
68
+ def hash
69
+ to_s.hash
70
+ end
71
+
72
+ def to_s
73
+ "<Relevance::Tarantula::Link href=#{href}, method=#{method}>"
74
+ end
75
+
76
+ end
@@ -0,0 +1,16 @@
1
+ class Relevance::Tarantula::LogGrabber
2
+ attr_accessor :path
3
+ def initialize(path)
4
+ @path = path
5
+ end
6
+
7
+ def clear!
8
+ File.open(@path, "w")
9
+ end
10
+
11
+ def grab!
12
+ File.read(@path)
13
+ ensure
14
+ clear!
15
+ end
16
+ end
@@ -0,0 +1,87 @@
1
+ require 'test/unit'
2
+
3
+ class Relevance::Tarantula::RailsIntegrationProxy
4
+ include Relevance::Tarantula
5
+ extend Relevance::Tarantula
6
+ extend Forwardable
7
+ attr_accessor :integration_test
8
+
9
+ def self.rails_integration_test(integration_test, options = {})
10
+ t = Crawler.new
11
+ t.max_url_length = options[:max_url_length] if options[:max_url_length]
12
+ t.proxy = RailsIntegrationProxy.new(integration_test)
13
+ t.handlers << HtmlDocumentHandler.new(t)
14
+ t.handlers << InvalidHtmlHandler.new
15
+ t.log_grabber = Relevance::Tarantula::LogGrabber.new(File.join(rails_root, "log/test.log"))
16
+ t.skip_uri_patterns << /logout$/
17
+ t.skip_uri_patterns.delete /^http/
18
+ t.skip_uri_patterns.push /^https?:\/\/(?!#{integration_test.host})/
19
+
20
+ t.transform_url_patterns += [
21
+ [/\?\d+$/, ''], # strip trailing numbers for assets
22
+ [/^https?:\/\/#{integration_test.host}/, ''] # strip full path down to relative
23
+ ]
24
+ t.test_name = t.proxy.integration_test.method_name
25
+ t.reporters << Relevance::Tarantula::HtmlReporter.new(t.report_dir)
26
+ t
27
+ end
28
+
29
+ def initialize(integration_test)
30
+ @integration_test = integration_test
31
+ @integration_test.meta.attr_accessor :response
32
+ end
33
+
34
+ [:get, :post, :put, :delete].each do |verb|
35
+ define_method(verb) do |url, *args|
36
+ integration_test.send(verb, url, *args)
37
+ process integration_test.response, verb, url, *args
38
+ end
39
+ end
40
+
41
+ def xhr(verb, url, *args)
42
+ integration_test.send(:xhr, verb, url, *args)
43
+ process integration_test.response, verb, url, *args
44
+ end
45
+
46
+ def process(response, verb, url, *args)
47
+ if verb == :get && response.code == '302'
48
+ location = response.headers['Location']
49
+
50
+ if location =~ /#{url}$/ # Schema change
51
+ integration_test.https!(!!(location =~ /^https/))
52
+ response = send(verb, url, *args)
53
+ elsif location =~ /#!?/ # AJAX load
54
+ response = send(:xhr, verb, url, *args)
55
+ end
56
+
57
+ elsif response.code == '404'
58
+ if File.exist?(static_content_path(url))
59
+ case ext = File.extension(url)
60
+ when /html|te?xt|css|js|jpe?g|gif|psd|png|eps|pdf|ico/
61
+ response.body = static_content_file(url)
62
+ response.headers["type"] = "text/#{ext}" # readable as response.content_type
63
+ response.meta.attr_accessor :code
64
+ response.code = "200"
65
+ else
66
+ log "Skipping unknown type #{url}"
67
+ end
68
+ end
69
+ end
70
+
71
+ # don't count on metaclass taking block, e.g.
72
+ # http://relevancellc.com/2008/2/12/how-should-metaclass-work
73
+ response.metaclass.class_eval do
74
+ include Relevance::CoreExtensions::Response
75
+ end
76
+
77
+ return response
78
+ end
79
+
80
+ def static_content_file(url)
81
+ File.read(static_content_path(url))
82
+ end
83
+
84
+ def static_content_path(url)
85
+ File.expand_path(File.join(rails_root, "public", url))
86
+ end
87
+ end
@@ -0,0 +1,12 @@
1
+ module Recording
2
+ def self.stderr
3
+ $stderr = recorder = StringIO.new
4
+ begin
5
+ yield
6
+ ensure
7
+ $stderr = STDERR
8
+ end
9
+ recorder.rewind
10
+ recorder.read
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ # Used to create a stub response when we didn't get back a real response
2
+ class Relevance::Tarantula::Response
3
+ HASHABLE_ATTRS = [:code, :body, :content_type]
4
+ attr_accessor *HASHABLE_ATTRS
5
+
6
+ def initialize(hash)
7
+ hash.each do |k,v|
8
+ raise ArgumentError, k unless HASHABLE_ATTRS.member?(k)
9
+ self.instance_variable_set("@#{k}", v)
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,77 @@
1
+ class Relevance::Tarantula::Result
2
+ HASHABLE_ATTRS = [:success, :method, :url, :response, :referrer, :data, :description, :log, :test_name]
3
+ DEFAULT_LOCALHOST = "http://localhost:3000"
4
+ attr_accessor *HASHABLE_ATTRS
5
+ include Relevance::Tarantula
6
+ include Relevance::Tarantula::HtmlReportHelper
7
+
8
+ def initialize(hash)
9
+ hash.each do |k,v|
10
+ raise ArgumentError, k unless HASHABLE_ATTRS.member?(k)
11
+ self.instance_variable_set("@#{k}", v)
12
+ end
13
+ end
14
+
15
+ def short_description
16
+ [method,url].join(" ")
17
+ end
18
+
19
+ def sequence_number
20
+ @sequence_number ||= (self.class.next_number += 1)
21
+ end
22
+
23
+ def file_name
24
+ "#{sequence_number}.html"
25
+ end
26
+
27
+ def code
28
+ response && response.code
29
+ end
30
+
31
+ def body
32
+ response && response.body
33
+ end
34
+
35
+ def full_url
36
+ "#{DEFAULT_LOCALHOST}#{url}"
37
+ end
38
+
39
+ ALLOW_NNN_FOR = /^allow_(\d\d\d)_for$/
40
+
41
+ class << self
42
+ attr_accessor :next_number
43
+
44
+ def handle(result)
45
+ retval = result.dup
46
+ retval.success = successful?(result.response) || can_skip_error?(result)
47
+ retval.description = "Bad HTTP Response" unless retval.success
48
+ retval
49
+ end
50
+
51
+ def success_codes
52
+ %w{200 201 302 401}
53
+ end
54
+
55
+ # allow_errors_for is a hash
56
+ # k=error code,
57
+ # v=array of matchers for urls that can skip said error
58
+ attr_accessor :allow_errors_for
59
+ def can_skip_error?(result)
60
+ coll = allow_errors_for[result.code]
61
+ return false unless coll
62
+ coll.any? {|item| item === result.url}
63
+ end
64
+
65
+ def successful?(response)
66
+ success_codes.member?(response.code)
67
+ end
68
+
69
+ def method_missing(meth, *args)
70
+ super unless ALLOW_NNN_FOR =~ meth.to_s
71
+ (allow_errors_for[$1] ||= []).push(*args)
72
+ end
73
+ end
74
+
75
+ self.allow_errors_for = {}
76
+ self.next_number = 0
77
+ end
@@ -0,0 +1,32 @@
1
+ <div id="<%= test_name %>">
2
+ <% %w{failures successes}.each do |result_type| %>
3
+ <table class="list tablesorter" cellspacing="0">
4
+ <caption><%= send(result_type).size %> <%= result_type.capitalize %></caption>
5
+ <thead>
6
+ <tr>
7
+ <th class="sort asc"><span>URL</span><span class="sort">&nbsp;</span></th>
8
+ <th><span>Action</span><span class="sort">&nbsp;</span></th>
9
+ <th><span>Response</span><span class="sort">&nbsp;</span></th>
10
+ <th class="left"><span>Description</span><span class="sort">&nbsp;</span></th>
11
+ <th><span>Referrer</span><span class="sort">&nbsp;</span></th>
12
+ </tr>
13
+ </thead>
14
+ <tfoot>
15
+ <tr><td colspan="5">&nbsp;</td></tr>
16
+ </tfoot>
17
+
18
+ <tbody>
19
+ <% send(result_type).sort{|x,y| y.code.to_s <=> x.code.to_s}.each_with_index do |result,i| %>
20
+ <tr class="<%= (i%2 == 0) ? 'even' : 'odd' %>">
21
+ <td class="left"><a href="<%= "#{test_name}/#{result.file_name}" %>"><%= result.url.ellipsize(50) %></a></td>
22
+ <td class="method"><%= result.method.to_s.upcase %></td> <!-- TODO Clean up demeter violation -->
23
+ <td><span class="<%= class_for_code(result.code) %>"><%= result.code %></span></td>
24
+ <td class="left"><%= result.description %></td>
25
+ <td class="left"><%= result.referrer.ellipsize(30) %></td>
26
+ </tr>
27
+ <% end %>
28
+ </tbody>
29
+ </table>
30
+ <br/>
31
+ <% end %>
32
+ </div>
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ begin
3
+ gem 'tidy'
4
+ require 'tidy'
5
+ rescue Gem::LoadError
6
+ puts "Tidy gem not available -- 'gem install tidy' to get it."
7
+ end
8
+
9
+ if defined? Tidy
10
+ Tidy.path = ENV['TIDY_PATH'] if ENV['TIDY_PATH']
11
+
12
+ class Relevance::Tarantula::TidyHandler
13
+ include Relevance::Tarantula
14
+ def initialize(options = {})
15
+ @options = {:show_warnings=>true}.merge(options)
16
+ end
17
+ def handle(result)
18
+ response = result.response
19
+ return unless response.html?
20
+ tidy = Tidy.open(@options) do |tidy|
21
+ xml = tidy.clean(response.body)
22
+ tidy
23
+ end
24
+ unless tidy.errors.blank?
25
+ error_result = result.dup
26
+ error_result.description = "Bad HTML (Tidy)"
27
+ error_result.data = tidy.errors.inspect
28
+ error_result
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ class Relevance::Tarantula::Transform
2
+ attr_accessor :from, :to
3
+ def initialize(from, to)
4
+ @from = from
5
+ @to = to
6
+ end
7
+ def [](string)
8
+ case to
9
+ when Proc
10
+ string.gsub(from, &to)
11
+ else
12
+ string.gsub(from, to)
13
+ end
14
+ end
15
+ end
16
+
17
+
@@ -0,0 +1,42 @@
1
+ require 'rake'
2
+
3
+ namespace :tarantula do
4
+
5
+ desc 'Run tarantula tests.'
6
+ task :test do
7
+ rm_rf "tmp/tarantula"
8
+ Rake::TestTask.new(:tarantula_test) do |t|
9
+ t.libs << 'test'
10
+ t.pattern = 'test/tarantula/**/*_test.rb'
11
+ t.verbose = true
12
+ end
13
+
14
+ Rake::Task[:tarantula_test].invoke
15
+ end
16
+
17
+ desc 'Run tarantula tests and open results in your browser.'
18
+ task :report do
19
+ begin
20
+ Rake::Task['tarantula:test'].invoke
21
+ rescue RuntimeError => e
22
+ puts e.message
23
+ end
24
+
25
+ Dir.glob("tmp/tarantula/**/index.html") do |file|
26
+ if PLATFORM['darwin']
27
+ system("open #{file}")
28
+ elsif PLATFORM[/linux/]
29
+ system("firefox #{file}")
30
+ else
31
+ puts "You can view tarantula results at #{file}"
32
+ end
33
+ end
34
+ end
35
+
36
+ desc 'Generate a default tarantula test'
37
+ task :setup do
38
+ mkdir_p "test/tarantula"
39
+ template_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "template", "tarantula_test.rb"))
40
+ cp template_path, "test/tarantula/"
41
+ end
42
+ end
@@ -0,0 +1,22 @@
1
+ require "#{File.dirname(__FILE__)}/../test_helper"
2
+ require "relevance/tarantula"
3
+
4
+ class TarantulaTest < ActionController::IntegrationTest
5
+ # Load enough test data to ensure that there's a link to every page in your
6
+ # application. Doing so allows Tarantula to follow those links and crawl
7
+ # every page. For many applications, you can load a decent data set by
8
+ # loading all fixtures.
9
+ fixtures :all
10
+
11
+ def test_tarantula
12
+ # If your application requires users to log in before accessing certain
13
+ # pages, uncomment the lines below and update them to allow this test to
14
+ # log in to your application. Doing so allows Tarantula to crawl the
15
+ # pages that are only accessible to logged-in users.
16
+ #
17
+ # post '/session', :login => 'quentin', :password => 'monkey'
18
+ # follow_redirect!
19
+
20
+ tarantula_crawl(self)
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,213 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: panmind-tarantula
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 3
9
+ - 3
10
+ version: 0.3.3
11
+ platform: ruby
12
+ authors:
13
+ - Relevance, Inc.
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-18 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: htmlentities
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 55
30
+ segments:
31
+ - 4
32
+ - 2
33
+ - 0
34
+ version: 4.2.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: hpricot
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 61
46
+ segments:
47
+ - 0
48
+ - 8
49
+ - 1
50
+ version: 0.8.1
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: micronaut
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ type: :development
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: log_buddy
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ type: :development
80
+ version_requirements: *id004
81
+ description: A big hairy fuzzy spider that crawls your site, wreaking havoc
82
+ email: opensource@thinkrelevance.com
83
+ executables: []
84
+
85
+ extensions: []
86
+
87
+ extra_rdoc_files:
88
+ - LICENSE
89
+ - README.rdoc
90
+ files:
91
+ - CHANGELOG
92
+ - README.rdoc
93
+ - Rakefile
94
+ - VERSION.yml
95
+ - examples/example_helper.rb
96
+ - examples/relevance/core_extensions/ellipsize_example.rb
97
+ - examples/relevance/core_extensions/file_example.rb
98
+ - examples/relevance/core_extensions/response_example.rb
99
+ - examples/relevance/core_extensions/test_case_example.rb
100
+ - examples/relevance/tarantula/attack_handler_example.rb
101
+ - examples/relevance/tarantula/basic_attack_example.rb
102
+ - examples/relevance/tarantula/crawler_example.rb
103
+ - examples/relevance/tarantula/form_example.rb
104
+ - examples/relevance/tarantula/form_submission_example.rb
105
+ - examples/relevance/tarantula/html_document_handler_example.rb
106
+ - examples/relevance/tarantula/html_report_helper_example.rb
107
+ - examples/relevance/tarantula/html_reporter_example.rb
108
+ - examples/relevance/tarantula/invalid_html_handler_example.rb
109
+ - examples/relevance/tarantula/io_reporter_example.rb
110
+ - examples/relevance/tarantula/link_example.rb
111
+ - examples/relevance/tarantula/log_grabber_example.rb
112
+ - examples/relevance/tarantula/rails_integration_proxy_example.rb
113
+ - examples/relevance/tarantula/result_example.rb
114
+ - examples/relevance/tarantula/tidy_handler_example.rb
115
+ - examples/relevance/tarantula/transform_example.rb
116
+ - examples/relevance/tarantula_example.rb
117
+ - laf/images/header_bg.jpg
118
+ - laf/images/logo.png
119
+ - laf/images/tagline.png
120
+ - laf/javascripts/jquery-1.2.3.js
121
+ - laf/javascripts/jquery-ui-tabs.js
122
+ - laf/javascripts/jquery.tablesorter.js
123
+ - laf/javascripts/tarantula.js
124
+ - laf/stylesheets/tarantula.css
125
+ - lib/relevance/core_extensions/ellipsize.rb
126
+ - lib/relevance/core_extensions/file.rb
127
+ - lib/relevance/core_extensions/metaclass.rb
128
+ - lib/relevance/core_extensions/response.rb
129
+ - lib/relevance/core_extensions/string_chars_fix.rb
130
+ - lib/relevance/core_extensions/test_case.rb
131
+ - lib/relevance/tarantula.rb
132
+ - lib/relevance/tarantula/attack.rb
133
+ - lib/relevance/tarantula/attack_handler.rb
134
+ - lib/relevance/tarantula/basic_attack.rb
135
+ - lib/relevance/tarantula/crawler.rb
136
+ - lib/relevance/tarantula/detail.html.erb
137
+ - lib/relevance/tarantula/form.rb
138
+ - lib/relevance/tarantula/form_submission.rb
139
+ - lib/relevance/tarantula/html_document_handler.rb
140
+ - lib/relevance/tarantula/html_report_helper.rb
141
+ - lib/relevance/tarantula/html_reporter.rb
142
+ - lib/relevance/tarantula/index.html.erb
143
+ - lib/relevance/tarantula/invalid_html_handler.rb
144
+ - lib/relevance/tarantula/io_reporter.rb
145
+ - lib/relevance/tarantula/link.rb
146
+ - lib/relevance/tarantula/log_grabber.rb
147
+ - lib/relevance/tarantula/rails_integration_proxy.rb
148
+ - lib/relevance/tarantula/recording.rb
149
+ - lib/relevance/tarantula/response.rb
150
+ - lib/relevance/tarantula/result.rb
151
+ - lib/relevance/tarantula/test_report.html.erb
152
+ - lib/relevance/tarantula/tidy_handler.rb
153
+ - lib/relevance/tarantula/transform.rb
154
+ - tasks/tarantula_tasks.rake
155
+ - template/tarantula_test.rb
156
+ - LICENSE
157
+ has_rdoc: true
158
+ homepage: http://github.com/Panmind/tarantula
159
+ licenses: []
160
+
161
+ post_install_message:
162
+ rdoc_options:
163
+ - --charset=UTF-8
164
+ require_paths:
165
+ - lib
166
+ required_ruby_version: !ruby/object:Gem::Requirement
167
+ none: false
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ hash: 3
172
+ segments:
173
+ - 0
174
+ version: "0"
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ none: false
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ hash: 3
181
+ segments:
182
+ - 0
183
+ version: "0"
184
+ requirements: []
185
+
186
+ rubyforge_project:
187
+ rubygems_version: 1.3.7
188
+ signing_key:
189
+ specification_version: 3
190
+ summary: A big hairy fuzzy spider that crawls your site, wreaking havoc
191
+ test_files:
192
+ - examples/example_helper.rb
193
+ - examples/relevance/core_extensions/ellipsize_example.rb
194
+ - examples/relevance/core_extensions/file_example.rb
195
+ - examples/relevance/core_extensions/response_example.rb
196
+ - examples/relevance/core_extensions/test_case_example.rb
197
+ - examples/relevance/tarantula/attack_handler_example.rb
198
+ - examples/relevance/tarantula/basic_attack_example.rb
199
+ - examples/relevance/tarantula/crawler_example.rb
200
+ - examples/relevance/tarantula/form_example.rb
201
+ - examples/relevance/tarantula/form_submission_example.rb
202
+ - examples/relevance/tarantula/html_document_handler_example.rb
203
+ - examples/relevance/tarantula/html_report_helper_example.rb
204
+ - examples/relevance/tarantula/html_reporter_example.rb
205
+ - examples/relevance/tarantula/invalid_html_handler_example.rb
206
+ - examples/relevance/tarantula/io_reporter_example.rb
207
+ - examples/relevance/tarantula/link_example.rb
208
+ - examples/relevance/tarantula/log_grabber_example.rb
209
+ - examples/relevance/tarantula/rails_integration_proxy_example.rb
210
+ - examples/relevance/tarantula/result_example.rb
211
+ - examples/relevance/tarantula/tidy_handler_example.rb
212
+ - examples/relevance/tarantula/transform_example.rb
213
+ - examples/relevance/tarantula_example.rb