##// END OF EJS Templates
Use simplecov for code coverage, rcov does not support ruby>=1.9....
Jean-Philippe Lang -
r13309:c3ba302f0de6
parent child
Show More
@@ -0,0 +1,70
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 #
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
18 require 'erb'
19 require 'cgi'
20
21 # A simple formatter for SimpleCov
22 module Redmine
23 module Coverage
24 class HtmlFormatter
25 def format(result)
26 File.open(File.join(output_path, "index.html"), "w") do |file|
27 file.puts template('index').result(binding)
28 end
29 result.source_files.each do |source_file|
30 File.open(File.join(output_path, source_file_result(source_file)), "w") do |file|
31 file.puts template('source').result(binding)
32 end
33 end
34 end
35
36 private
37
38 def now
39 @now = Time.now.utc
40 end
41
42 def output_path
43 SimpleCov.coverage_path
44 end
45
46 def shortened_filename(source_file)
47 source_file.filename.gsub(SimpleCov.root, '.').gsub(/^\.\//, '')
48 end
49
50 def link_to_source_file(source_file)
51 %(<a href="#{source_file_result source_file}">#{shortened_filename source_file}</a>)
52 end
53
54 def source_file_result(source_file)
55 shortened_filename(source_file).gsub('/', '__')+'.html'
56 end
57
58 def revision_link
59 if revision = Redmine::VERSION.revision
60 %(<a href="http://www.redmine.org/projects/redmine/repository/revisions/#{revision}">r#{revision}</a>)
61 end
62 end
63
64 # Returns the an erb instance for the template of given name
65 def template(name)
66 ERB.new(File.read(File.join(File.dirname(__FILE__), 'views', "#{name}.erb")))
67 end
68 end
69 end
70 end
@@ -0,0 +1,60
1 <!DOCTYPE html>
2 <head>
3 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
4 <title>Redmine code coverage</title>
5 <style>
6 html {overflow-y:scroll;}
7 body {font-family:"Lucida Grande","Lucida Sans",Verdana,Helvetica,Arial,sans-serif; font-size:80%;}
8 h1 {color:#777; margin-bottom:0.2em;}
9 h2 {color:#aaa;margin-top:1em;font-size:18px;}
10 table {width:100%; border-collapse:collapse;}
11 th, td {border:1px solid #e2e2e2;}
12 td {text-align:right; font-family:"Bitstream Vera Sans Mono","Monaco","Courier New",monospace;}
13 td.filename {text-align:left; font-family:"Lucida Grande","Lucida Sans",Verdana,Helvetica,Arial,sans-serif;}
14 th {background:#e2e2e2;}
15 #generation {color:#777; font-size:90%;}
16 a, a:link, a:visited {color:#169; text-decoration:none;}
17 a:hover, a:active {color:#c61a1a; text-decoration:underline;}
18 div.percent {height:1em; empty-cells:show; padding:0px; border-collapse:collapse; width:100px !important; float:left; margin:0 0.5em 0 0.5em;}
19 div.percent div {float:left; height:1em; padding:0px !important;}
20 div.percent div.covered {background:#8c7;}
21 div.percent div.uncovered {background:#d76;}
22 </style>
23 </head>
24 <body>
25 <h1>Redmine code coverage</h1>
26 <p id='generation'>
27 Generated on <%= now %> (<%= revision_link %>).
28 More information about this environment at <a href='http://www.redmine.org/projects/redmine/wiki/Continuous_integration'>redmine.org</a>.
29 </p>
30
31 <table class="file_list">
32 <thead>
33 <tr>
34 <th>File</th>
35 <th colspan="2">% covered</th>
36 <th>Lines</th>
37 <th>Relevant</th>
38 <th>Covered</th>
39 </tr>
40 </thead>
41 <tbody>
42 <% result.source_files.each do |source_file| %>
43 <tr>
44 <td class="filename"><%= link_to_source_file(source_file) %></td>
45 <td><%= "%.1f" % source_file.covered_percent %> %</td>
46 <td>
47 <div class="percent">
48 <div class="covered" style="width:<%= source_file.covered_percent.to_i %>px"></div>
49 <div class="uncovered" style="width:<%= 100 - source_file.covered_percent.to_i %>px"></div>
50 </div>
51 </td>
52 <td><%= source_file.lines.count %></td>
53 <td><%= source_file.covered_lines.count + source_file.missed_lines.count %></td>
54 <td><%= source_file.covered_lines.count %></td>
55 </tr>
56 <% end %>
57 </tbody>
58 </table>
59 </body>
60 </html>
@@ -0,0 +1,41
1 <!DOCTYPE html>
2 <head>
3 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
4 <title>Redmine code coverage</title>
5 <style>
6 html {overflow-y:scroll;}
7 body {font-family:"Lucida Grande","Lucida Sans",Verdana,Helvetica,Arial,sans-serif; font-size:80%;}
8 h1 {color:#777; margin-bottom:0.2em;}
9 h2 {color:#aaa; margin-top:1em; font-size:18px;}
10 #generation {color:#777; font-size:90%;}
11 a, a:link, a:visited {color:#169; text-decoration:none;}
12 a:hover, a:active {color:#c61a1a; text-decoration:underline;}
13 pre, code {
14 color: #000000;
15 font-family: "Bitstream Vera Sans Mono","Monaco","Courier New",monospace;
16 font-size: 95%;
17 line-height: 1.3em;
18 margin-top: 0;
19 margin-bottom: 0;
20 padding: 0;
21 }
22 div.source {border:1px solid #e2e2e2;}
23 .covered {background:#bed2be;}
24 .missed {background:#fba;}
25 .never {background:#eee;}
26 </style>
27 </head>
28 <body>
29 <h1>Redmine code coverage</h1>
30 <p id='generation'>
31 Generated on <%= now %> (<%= revision_link %>).
32 More information about this environment at <a href='http://www.redmine.org/projects/redmine/wiki/Continuous_integration'>redmine.org</a>.
33 </p>
34 <h2><%= shortened_filename source_file %> (<%= "%.1f" % source_file.covered_percent %> %)</h2>
35
36 <div class="source">
37 <% source_file.lines.each_with_index do |line, i| %>
38 <pre class="<%= line.status %>" data-hits="<%= line.coverage ? line.coverage : '' %>" data-linenumber="<%= line.number %>"
39 ><code class="ruby"><%= i.to_s.rjust 4 %> <%= CGI.escapeHTML(line.src.chomp) %></code></pre>
40 <% end %>
41 </div>
@@ -1,103 +1,104
1 source 'https://rubygems.org'
1 source 'https://rubygems.org'
2
2
3 gem "rails", "4.1.8"
3 gem "rails", "4.1.8"
4 gem "jquery-rails", "~> 3.1.1"
4 gem "jquery-rails", "~> 3.1.1"
5 gem "coderay", "~> 1.1.0"
5 gem "coderay", "~> 1.1.0"
6 gem "builder", ">= 3.0.4"
6 gem "builder", ">= 3.0.4"
7 gem "request_store", "1.0.5"
7 gem "request_store", "1.0.5"
8 gem "mime-types"
8 gem "mime-types"
9 gem "awesome_nested_set", "3.0.0"
9 gem "awesome_nested_set", "3.0.0"
10 gem "protected_attributes"
10 gem "protected_attributes"
11 gem "actionpack-action_caching"
11 gem "actionpack-action_caching"
12
12
13 # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
13 # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
14 gem 'tzinfo-data', platforms: [:mingw, :x64_mingw, :mswin, :jruby]
14 gem 'tzinfo-data', platforms: [:mingw, :x64_mingw, :mswin, :jruby]
15 gem "rbpdf", "~> 1.18.2"
15 gem "rbpdf", "~> 1.18.2"
16
16
17 # Optional gem for LDAP authentication
17 # Optional gem for LDAP authentication
18 group :ldap do
18 group :ldap do
19 gem "net-ldap", "~> 0.3.1"
19 gem "net-ldap", "~> 0.3.1"
20 end
20 end
21
21
22 # Optional gem for OpenID authentication
22 # Optional gem for OpenID authentication
23 group :openid do
23 group :openid do
24 gem "ruby-openid", "~> 2.3.0", :require => "openid"
24 gem "ruby-openid", "~> 2.3.0", :require => "openid"
25 gem "rack-openid"
25 gem "rack-openid"
26 end
26 end
27
27
28 platforms :mri, :mingw, :x64_mingw do
28 platforms :mri, :mingw, :x64_mingw do
29 # Optional gem for exporting the gantt to a PNG file, not supported with jruby
29 # Optional gem for exporting the gantt to a PNG file, not supported with jruby
30 group :rmagick do
30 group :rmagick do
31 gem "rmagick", ">= 2.0.0"
31 gem "rmagick", ">= 2.0.0"
32 end
32 end
33
33
34 # Optional Markdown support, not for JRuby
34 # Optional Markdown support, not for JRuby
35 group :markdown do
35 group :markdown do
36 gem "redcarpet", "~> 3.1.2"
36 gem "redcarpet", "~> 3.1.2"
37 end
37 end
38 end
38 end
39
39
40 platforms :jruby do
40 platforms :jruby do
41 # jruby-openssl is bundled with JRuby 1.7.0
41 # jruby-openssl is bundled with JRuby 1.7.0
42 gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
42 gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
43 gem "activerecord-jdbc-adapter", "~> 1.3.2"
43 gem "activerecord-jdbc-adapter", "~> 1.3.2"
44 end
44 end
45
45
46 # Include database gems for the adapters found in the database
46 # Include database gems for the adapters found in the database
47 # configuration file
47 # configuration file
48 require 'erb'
48 require 'erb'
49 require 'yaml'
49 require 'yaml'
50 database_file = File.join(File.dirname(__FILE__), "config/database.yml")
50 database_file = File.join(File.dirname(__FILE__), "config/database.yml")
51 if File.exist?(database_file)
51 if File.exist?(database_file)
52 database_config = YAML::load(ERB.new(IO.read(database_file)).result)
52 database_config = YAML::load(ERB.new(IO.read(database_file)).result)
53 adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
53 adapters = database_config.values.map {|c| c['adapter']}.compact.uniq
54 if adapters.any?
54 if adapters.any?
55 adapters.each do |adapter|
55 adapters.each do |adapter|
56 case adapter
56 case adapter
57 when 'mysql2'
57 when 'mysql2'
58 gem "mysql2", "~> 0.3.11", :platforms => [:mri, :mingw, :x64_mingw]
58 gem "mysql2", "~> 0.3.11", :platforms => [:mri, :mingw, :x64_mingw]
59 gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
59 gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
60 when 'mysql'
60 when 'mysql'
61 gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
61 gem "activerecord-jdbcmysql-adapter", :platforms => :jruby
62 when /postgresql/
62 when /postgresql/
63 gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw, :x64_mingw]
63 gem "pg", ">= 0.11.0", :platforms => [:mri, :mingw, :x64_mingw]
64 gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
64 gem "activerecord-jdbcpostgresql-adapter", :platforms => :jruby
65 when /sqlite3/
65 when /sqlite3/
66 gem "sqlite3", :platforms => [:mri, :mingw, :x64_mingw]
66 gem "sqlite3", :platforms => [:mri, :mingw, :x64_mingw]
67 gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
67 gem "activerecord-jdbcsqlite3-adapter", :platforms => :jruby
68 when /sqlserver/
68 when /sqlserver/
69 gem "tiny_tds", "~> 0.6.2", :platforms => [:mri, :mingw, :x64_mingw]
69 gem "tiny_tds", "~> 0.6.2", :platforms => [:mri, :mingw, :x64_mingw]
70 gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw, :x64_mingw]
70 gem "activerecord-sqlserver-adapter", :platforms => [:mri, :mingw, :x64_mingw]
71 else
71 else
72 warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
72 warn("Unknown database adapter `#{adapter}` found in config/database.yml, use Gemfile.local to load your own database gems")
73 end
73 end
74 end
74 end
75 else
75 else
76 warn("No adapter found in config/database.yml, please configure it first")
76 warn("No adapter found in config/database.yml, please configure it first")
77 end
77 end
78 else
78 else
79 warn("Please configure your config/database.yml first")
79 warn("Please configure your config/database.yml first")
80 end
80 end
81
81
82 group :development do
82 group :development do
83 gem "rdoc", ">= 2.4.2"
83 gem "rdoc", ">= 2.4.2"
84 gem "yard"
84 gem "yard"
85 end
85 end
86
86
87 group :test do
87 group :test do
88 gem "minitest"
88 gem "minitest"
89 gem "mocha", "~> 1.0.0", :require => 'mocha/api'
89 gem "mocha", "~> 1.0.0", :require => 'mocha/api'
90 gem "simplecov", "~> 0.9.1", :require => false
90 # For running UI tests
91 # For running UI tests
91 gem "capybara", "~> 2.1.0"
92 gem "capybara", "~> 2.1.0"
92 gem "selenium-webdriver"
93 gem "selenium-webdriver"
93 end
94 end
94
95
95 local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
96 local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
96 if File.exists?(local_gemfile)
97 if File.exists?(local_gemfile)
97 eval_gemfile local_gemfile
98 eval_gemfile local_gemfile
98 end
99 end
99
100
100 # Load plugins' Gemfiles
101 # Load plugins' Gemfiles
101 Dir.glob File.expand_path("../plugins/*/{Gemfile,PluginGemfile}", __FILE__) do |file|
102 Dir.glob File.expand_path("../plugins/*/{Gemfile,PluginGemfile}", __FILE__) do |file|
102 eval_gemfile file
103 eval_gemfile file
103 end
104 end
@@ -1,114 +1,110
1 ### From http://svn.geekdaily.org/public/rails/plugins/generally_useful/tasks/coverage_via_rcov.rake
2
3 namespace :test do
1 namespace :test do
4 desc 'Measures test coverage'
2 desc 'Measures test coverage'
5 task :coverage do
3 task :coverage do
6 rm_f "coverage"
4 rm_f "coverage"
7 rm_f "coverage.data"
5 ENV["COVERAGE"] = "1"
8 rcov = "rcov --rails --aggregate coverage.data --text-summary -Ilib --html --exclude gems/"
6 Rake::Task["test"].invoke
9 files = %w(unit functional integration).map {|dir| Dir.glob("test/#{dir}/**/*_test.rb")}.flatten.join(" ")
10 system("#{rcov} #{files}")
11 end
7 end
12
8
13 desc 'Run unit and functional scm tests'
9 desc 'Run unit and functional scm tests'
14 task :scm do
10 task :scm do
15 errors = %w(test:scm:units test:scm:functionals).collect do |task|
11 errors = %w(test:scm:units test:scm:functionals).collect do |task|
16 begin
12 begin
17 Rake::Task[task].invoke
13 Rake::Task[task].invoke
18 nil
14 nil
19 rescue => e
15 rescue => e
20 task
16 task
21 end
17 end
22 end.compact
18 end.compact
23 abort "Errors running #{errors.to_sentence(:locale => :en)}!" if errors.any?
19 abort "Errors running #{errors.to_sentence(:locale => :en)}!" if errors.any?
24 end
20 end
25
21
26 namespace :scm do
22 namespace :scm do
27 namespace :setup do
23 namespace :setup do
28 desc "Creates directory for test repositories"
24 desc "Creates directory for test repositories"
29 task :create_dir => :environment do
25 task :create_dir => :environment do
30 FileUtils.mkdir_p Rails.root + '/tmp/test'
26 FileUtils.mkdir_p Rails.root + '/tmp/test'
31 end
27 end
32
28
33 supported_scms = [:subversion, :cvs, :bazaar, :mercurial, :git, :darcs, :filesystem]
29 supported_scms = [:subversion, :cvs, :bazaar, :mercurial, :git, :darcs, :filesystem]
34
30
35 desc "Creates a test subversion repository"
31 desc "Creates a test subversion repository"
36 task :subversion => :create_dir do
32 task :subversion => :create_dir do
37 repo_path = "tmp/test/subversion_repository"
33 repo_path = "tmp/test/subversion_repository"
38 unless File.exists?(repo_path)
34 unless File.exists?(repo_path)
39 system "svnadmin create #{repo_path}"
35 system "svnadmin create #{repo_path}"
40 system "gunzip < test/fixtures/repositories/subversion_repository.dump.gz | svnadmin load #{repo_path}"
36 system "gunzip < test/fixtures/repositories/subversion_repository.dump.gz | svnadmin load #{repo_path}"
41 end
37 end
42 end
38 end
43
39
44 desc "Creates a test mercurial repository"
40 desc "Creates a test mercurial repository"
45 task :mercurial => :create_dir do
41 task :mercurial => :create_dir do
46 repo_path = "tmp/test/mercurial_repository"
42 repo_path = "tmp/test/mercurial_repository"
47 unless File.exists?(repo_path)
43 unless File.exists?(repo_path)
48 bundle_path = "test/fixtures/repositories/mercurial_repository.hg"
44 bundle_path = "test/fixtures/repositories/mercurial_repository.hg"
49 system "hg init #{repo_path}"
45 system "hg init #{repo_path}"
50 system "hg -R #{repo_path} pull #{bundle_path}"
46 system "hg -R #{repo_path} pull #{bundle_path}"
51 end
47 end
52 end
48 end
53
49
54 def extract_tar_gz(prefix)
50 def extract_tar_gz(prefix)
55 unless File.exists?("tmp/test/#{prefix}_repository")
51 unless File.exists?("tmp/test/#{prefix}_repository")
56 # system "gunzip < test/fixtures/repositories/#{prefix}_repository.tar.gz | tar -xv -C tmp/test"
52 # system "gunzip < test/fixtures/repositories/#{prefix}_repository.tar.gz | tar -xv -C tmp/test"
57 system "tar -xvz -C tmp/test -f test/fixtures/repositories/#{prefix}_repository.tar.gz"
53 system "tar -xvz -C tmp/test -f test/fixtures/repositories/#{prefix}_repository.tar.gz"
58 end
54 end
59 end
55 end
60
56
61 (supported_scms - [:subversion, :mercurial]).each do |scm|
57 (supported_scms - [:subversion, :mercurial]).each do |scm|
62 desc "Creates a test #{scm} repository"
58 desc "Creates a test #{scm} repository"
63 task scm => :create_dir do
59 task scm => :create_dir do
64 extract_tar_gz(scm)
60 extract_tar_gz(scm)
65 end
61 end
66 end
62 end
67
63
68 desc "Creates all test repositories"
64 desc "Creates all test repositories"
69 task :all => supported_scms
65 task :all => supported_scms
70 end
66 end
71
67
72 desc "Updates installed test repositories"
68 desc "Updates installed test repositories"
73 task :update => :environment do
69 task :update => :environment do
74 require 'fileutils'
70 require 'fileutils'
75 Dir.glob("tmp/test/*_repository").each do |dir|
71 Dir.glob("tmp/test/*_repository").each do |dir|
76 next unless File.basename(dir) =~ %r{^(.+)_repository$} && File.directory?(dir)
72 next unless File.basename(dir) =~ %r{^(.+)_repository$} && File.directory?(dir)
77 scm = $1
73 scm = $1
78 next unless fixture = Dir.glob("test/fixtures/repositories/#{scm}_repository.*").first
74 next unless fixture = Dir.glob("test/fixtures/repositories/#{scm}_repository.*").first
79 next if File.stat(dir).ctime > File.stat(fixture).mtime
75 next if File.stat(dir).ctime > File.stat(fixture).mtime
80
76
81 FileUtils.rm_rf dir
77 FileUtils.rm_rf dir
82 Rake::Task["test:scm:setup:#{scm}"].execute
78 Rake::Task["test:scm:setup:#{scm}"].execute
83 end
79 end
84 end
80 end
85
81
86 Rake::TestTask.new(:units => "db:test:prepare") do |t|
82 Rake::TestTask.new(:units => "db:test:prepare") do |t|
87 t.libs << "test"
83 t.libs << "test"
88 t.verbose = true
84 t.verbose = true
89 t.test_files = FileList['test/unit/repository*_test.rb'] + FileList['test/unit/lib/redmine/scm/**/*_test.rb']
85 t.test_files = FileList['test/unit/repository*_test.rb'] + FileList['test/unit/lib/redmine/scm/**/*_test.rb']
90 end
86 end
91 Rake::Task['test:scm:units'].comment = "Run the scm unit tests"
87 Rake::Task['test:scm:units'].comment = "Run the scm unit tests"
92
88
93 Rake::TestTask.new(:functionals => "db:test:prepare") do |t|
89 Rake::TestTask.new(:functionals => "db:test:prepare") do |t|
94 t.libs << "test"
90 t.libs << "test"
95 t.verbose = true
91 t.verbose = true
96 t.test_files = FileList['test/functional/repositories*_test.rb']
92 t.test_files = FileList['test/functional/repositories*_test.rb']
97 end
93 end
98 Rake::Task['test:scm:functionals'].comment = "Run the scm functional tests"
94 Rake::Task['test:scm:functionals'].comment = "Run the scm functional tests"
99 end
95 end
100
96
101 Rake::TestTask.new(:routing) do |t|
97 Rake::TestTask.new(:routing) do |t|
102 t.libs << "test"
98 t.libs << "test"
103 t.verbose = true
99 t.verbose = true
104 t.test_files = FileList['test/integration/routing/*_test.rb'] + FileList['test/integration/api_test/*_routing_test.rb']
100 t.test_files = FileList['test/integration/routing/*_test.rb'] + FileList['test/integration/api_test/*_routing_test.rb']
105 end
101 end
106 Rake::Task['test:routing'].comment = "Run the routing tests"
102 Rake::Task['test:routing'].comment = "Run the routing tests"
107
103
108 Rake::TestTask.new(:ui => "db:test:prepare") do |t|
104 Rake::TestTask.new(:ui => "db:test:prepare") do |t|
109 t.libs << "test"
105 t.libs << "test"
110 t.verbose = true
106 t.verbose = true
111 t.test_files = FileList['test/ui/**/*_test.rb']
107 t.test_files = FileList['test/ui/**/*_test.rb']
112 end
108 end
113 Rake::Task['test:ui'].comment = "Run the UI tests with Capybara (PhantomJS listening on port 4444 is required)"
109 Rake::Task['test:ui'].comment = "Run the UI tests with Capybara (PhantomJS listening on port 4444 is required)"
114 end
110 end
@@ -1,281 +1,288
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
2 # Copyright (C) 2006-2014 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 if ENV["COVERAGE"]
19 require 'simplecov'
20 require File.expand_path(File.dirname(__FILE__) + "/coverage/html_formatter")
21 SimpleCov.formatter = Redmine::Coverage::HtmlFormatter
22 SimpleCov.start 'rails'
23 end
24
18 ENV["RAILS_ENV"] = "test"
25 ENV["RAILS_ENV"] = "test"
19 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
26 require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
20 require 'rails/test_help'
27 require 'rails/test_help'
21 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
28 require Rails.root.join('test', 'mocks', 'open_id_authentication_mock.rb').to_s
22
29
23 require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
30 require File.expand_path(File.dirname(__FILE__) + '/object_helpers')
24 include ObjectHelpers
31 include ObjectHelpers
25
32
26 require 'awesome_nested_set/version'
33 require 'awesome_nested_set/version'
27 require 'net/ldap'
34 require 'net/ldap'
28
35
29 class ActionView::TestCase
36 class ActionView::TestCase
30 helper :application
37 helper :application
31 include ApplicationHelper
38 include ApplicationHelper
32 end
39 end
33
40
34 class ActiveSupport::TestCase
41 class ActiveSupport::TestCase
35 include ActionDispatch::TestProcess
42 include ActionDispatch::TestProcess
36
43
37 self.use_transactional_fixtures = true
44 self.use_transactional_fixtures = true
38 self.use_instantiated_fixtures = false
45 self.use_instantiated_fixtures = false
39
46
40 #ESCAPED_CANT = 'can&#x27;t'
47 #ESCAPED_CANT = 'can&#x27;t'
41 #ESCAPED_UCANT = 'Can&#x27;t'
48 #ESCAPED_UCANT = 'Can&#x27;t'
42 # Rails 4.0.2
49 # Rails 4.0.2
43 ESCAPED_CANT = 'can&#39;t'
50 ESCAPED_CANT = 'can&#39;t'
44 ESCAPED_UCANT = 'Can&#39;t'
51 ESCAPED_UCANT = 'Can&#39;t'
45
52
46 def uploaded_test_file(name, mime)
53 def uploaded_test_file(name, mime)
47 fixture_file_upload("files/#{name}", mime, true)
54 fixture_file_upload("files/#{name}", mime, true)
48 end
55 end
49
56
50 # Mock out a file
57 # Mock out a file
51 def self.mock_file
58 def self.mock_file
52 file = 'a_file.png'
59 file = 'a_file.png'
53 file.stubs(:size).returns(32)
60 file.stubs(:size).returns(32)
54 file.stubs(:original_filename).returns('a_file.png')
61 file.stubs(:original_filename).returns('a_file.png')
55 file.stubs(:content_type).returns('image/png')
62 file.stubs(:content_type).returns('image/png')
56 file.stubs(:read).returns(false)
63 file.stubs(:read).returns(false)
57 file
64 file
58 end
65 end
59
66
60 def mock_file
67 def mock_file
61 self.class.mock_file
68 self.class.mock_file
62 end
69 end
63
70
64 def mock_file_with_options(options={})
71 def mock_file_with_options(options={})
65 file = ''
72 file = ''
66 file.stubs(:size).returns(32)
73 file.stubs(:size).returns(32)
67 original_filename = options[:original_filename] || nil
74 original_filename = options[:original_filename] || nil
68 file.stubs(:original_filename).returns(original_filename)
75 file.stubs(:original_filename).returns(original_filename)
69 content_type = options[:content_type] || nil
76 content_type = options[:content_type] || nil
70 file.stubs(:content_type).returns(content_type)
77 file.stubs(:content_type).returns(content_type)
71 file.stubs(:read).returns(false)
78 file.stubs(:read).returns(false)
72 file
79 file
73 end
80 end
74
81
75 # Use a temporary directory for attachment related tests
82 # Use a temporary directory for attachment related tests
76 def set_tmp_attachments_directory
83 def set_tmp_attachments_directory
77 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
84 Dir.mkdir "#{Rails.root}/tmp/test" unless File.directory?("#{Rails.root}/tmp/test")
78 unless File.directory?("#{Rails.root}/tmp/test/attachments")
85 unless File.directory?("#{Rails.root}/tmp/test/attachments")
79 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
86 Dir.mkdir "#{Rails.root}/tmp/test/attachments"
80 end
87 end
81 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
88 Attachment.storage_path = "#{Rails.root}/tmp/test/attachments"
82 end
89 end
83
90
84 def set_fixtures_attachments_directory
91 def set_fixtures_attachments_directory
85 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
92 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
86 end
93 end
87
94
88 def with_settings(options, &block)
95 def with_settings(options, &block)
89 saved_settings = options.keys.inject({}) do |h, k|
96 saved_settings = options.keys.inject({}) do |h, k|
90 h[k] = case Setting[k]
97 h[k] = case Setting[k]
91 when Symbol, false, true, nil
98 when Symbol, false, true, nil
92 Setting[k]
99 Setting[k]
93 else
100 else
94 Setting[k].dup
101 Setting[k].dup
95 end
102 end
96 h
103 h
97 end
104 end
98 options.each {|k, v| Setting[k] = v}
105 options.each {|k, v| Setting[k] = v}
99 yield
106 yield
100 ensure
107 ensure
101 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
108 saved_settings.each {|k, v| Setting[k] = v} if saved_settings
102 end
109 end
103
110
104 # Yields the block with user as the current user
111 # Yields the block with user as the current user
105 def with_current_user(user, &block)
112 def with_current_user(user, &block)
106 saved_user = User.current
113 saved_user = User.current
107 User.current = user
114 User.current = user
108 yield
115 yield
109 ensure
116 ensure
110 User.current = saved_user
117 User.current = saved_user
111 end
118 end
112
119
113 def with_locale(locale, &block)
120 def with_locale(locale, &block)
114 saved_localed = ::I18n.locale
121 saved_localed = ::I18n.locale
115 ::I18n.locale = locale
122 ::I18n.locale = locale
116 yield
123 yield
117 ensure
124 ensure
118 ::I18n.locale = saved_localed
125 ::I18n.locale = saved_localed
119 end
126 end
120
127
121 def self.ldap_configured?
128 def self.ldap_configured?
122 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
129 @test_ldap = Net::LDAP.new(:host => '127.0.0.1', :port => 389)
123 return @test_ldap.bind
130 return @test_ldap.bind
124 rescue Exception => e
131 rescue Exception => e
125 # LDAP is not listening
132 # LDAP is not listening
126 return nil
133 return nil
127 end
134 end
128
135
129 def self.convert_installed?
136 def self.convert_installed?
130 Redmine::Thumbnail.convert_available?
137 Redmine::Thumbnail.convert_available?
131 end
138 end
132
139
133 # Returns the path to the test +vendor+ repository
140 # Returns the path to the test +vendor+ repository
134 def self.repository_path(vendor)
141 def self.repository_path(vendor)
135 path = Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
142 path = Rails.root.join("tmp/test/#{vendor.downcase}_repository").to_s
136 # Unlike ruby, JRuby returns Rails.root with backslashes under Windows
143 # Unlike ruby, JRuby returns Rails.root with backslashes under Windows
137 path.tr("\\", "/")
144 path.tr("\\", "/")
138 end
145 end
139
146
140 # Returns the url of the subversion test repository
147 # Returns the url of the subversion test repository
141 def self.subversion_repository_url
148 def self.subversion_repository_url
142 path = repository_path('subversion')
149 path = repository_path('subversion')
143 path = '/' + path unless path.starts_with?('/')
150 path = '/' + path unless path.starts_with?('/')
144 "file://#{path}"
151 "file://#{path}"
145 end
152 end
146
153
147 # Returns true if the +vendor+ test repository is configured
154 # Returns true if the +vendor+ test repository is configured
148 def self.repository_configured?(vendor)
155 def self.repository_configured?(vendor)
149 File.directory?(repository_path(vendor))
156 File.directory?(repository_path(vendor))
150 end
157 end
151
158
152 def repository_path_hash(arr)
159 def repository_path_hash(arr)
153 hs = {}
160 hs = {}
154 hs[:path] = arr.join("/")
161 hs[:path] = arr.join("/")
155 hs[:param] = arr.join("/")
162 hs[:param] = arr.join("/")
156 hs
163 hs
157 end
164 end
158
165
159 def assert_save(object)
166 def assert_save(object)
160 saved = object.save
167 saved = object.save
161 message = "#{object.class} could not be saved"
168 message = "#{object.class} could not be saved"
162 errors = object.errors.full_messages.map {|m| "- #{m}"}
169 errors = object.errors.full_messages.map {|m| "- #{m}"}
163 message << ":\n#{errors.join("\n")}" if errors.any?
170 message << ":\n#{errors.join("\n")}" if errors.any?
164 assert_equal true, saved, message
171 assert_equal true, saved, message
165 end
172 end
166
173
167 def assert_select_error(arg)
174 def assert_select_error(arg)
168 assert_select '#errorExplanation', :text => arg
175 assert_select '#errorExplanation', :text => arg
169 end
176 end
170
177
171 def assert_include(expected, s, message=nil)
178 def assert_include(expected, s, message=nil)
172 assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"")
179 assert s.include?(expected), (message || "\"#{expected}\" not found in \"#{s}\"")
173 end
180 end
174
181
175 def assert_not_include(expected, s, message=nil)
182 def assert_not_include(expected, s, message=nil)
176 assert !s.include?(expected), (message || "\"#{expected}\" found in \"#{s}\"")
183 assert !s.include?(expected), (message || "\"#{expected}\" found in \"#{s}\"")
177 end
184 end
178
185
179 def assert_select_in(text, *args, &block)
186 def assert_select_in(text, *args, &block)
180 d = HTML::Document.new(CGI::unescapeHTML(String.new(text))).root
187 d = HTML::Document.new(CGI::unescapeHTML(String.new(text))).root
181 assert_select(d, *args, &block)
188 assert_select(d, *args, &block)
182 end
189 end
183
190
184 def assert_mail_body_match(expected, mail, message=nil)
191 def assert_mail_body_match(expected, mail, message=nil)
185 if expected.is_a?(String)
192 if expected.is_a?(String)
186 assert_include expected, mail_body(mail), message
193 assert_include expected, mail_body(mail), message
187 else
194 else
188 assert_match expected, mail_body(mail), message
195 assert_match expected, mail_body(mail), message
189 end
196 end
190 end
197 end
191
198
192 def assert_mail_body_no_match(expected, mail, message=nil)
199 def assert_mail_body_no_match(expected, mail, message=nil)
193 if expected.is_a?(String)
200 if expected.is_a?(String)
194 assert_not_include expected, mail_body(mail), message
201 assert_not_include expected, mail_body(mail), message
195 else
202 else
196 assert_no_match expected, mail_body(mail), message
203 assert_no_match expected, mail_body(mail), message
197 end
204 end
198 end
205 end
199
206
200 def mail_body(mail)
207 def mail_body(mail)
201 mail.parts.first.body.encoded
208 mail.parts.first.body.encoded
202 end
209 end
203
210
204 # awesome_nested_set new node lft and rgt value changed this refactor revision.
211 # awesome_nested_set new node lft and rgt value changed this refactor revision.
205 # https://github.com/collectiveidea/awesome_nested_set/commit/199fca9bb938e40200cd90714dc69247ef017c61
212 # https://github.com/collectiveidea/awesome_nested_set/commit/199fca9bb938e40200cd90714dc69247ef017c61
206 # The reason of behavior change is that "self.class.base_class.unscoped" was added to this line.
213 # The reason of behavior change is that "self.class.base_class.unscoped" was added to this line.
207 # https://github.com/collectiveidea/awesome_nested_set/commit/199fca9bb9#diff-f61b59a5e6319024e211b0ffdd0e4ef1R273
214 # https://github.com/collectiveidea/awesome_nested_set/commit/199fca9bb9#diff-f61b59a5e6319024e211b0ffdd0e4ef1R273
208 # It seems correct behavior because of this line comment.
215 # It seems correct behavior because of this line comment.
209 # https://github.com/collectiveidea/awesome_nested_set/blame/199fca9bb9/lib/awesome_nested_set/model.rb#L278
216 # https://github.com/collectiveidea/awesome_nested_set/blame/199fca9bb9/lib/awesome_nested_set/model.rb#L278
210 def new_issue_lft
217 def new_issue_lft
211 # ::AwesomeNestedSet::VERSION > "2.1.6" ? Issue.maximum(:rgt) + 1 : 1
218 # ::AwesomeNestedSet::VERSION > "2.1.6" ? Issue.maximum(:rgt) + 1 : 1
212 Issue.maximum(:rgt) + 1
219 Issue.maximum(:rgt) + 1
213 end
220 end
214 end
221 end
215
222
216 module Redmine
223 module Redmine
217 class RoutingTest < ActionDispatch::IntegrationTest
224 class RoutingTest < ActionDispatch::IntegrationTest
218 def should_route(arg)
225 def should_route(arg)
219 arg = arg.dup
226 arg = arg.dup
220 request = arg.keys.detect {|key| key.is_a?(String)}
227 request = arg.keys.detect {|key| key.is_a?(String)}
221 raise ArgumentError unless request
228 raise ArgumentError unless request
222 options = arg.slice!(request)
229 options = arg.slice!(request)
223
230
224 raise ArgumentError unless request =~ /\A(GET|POST|PUT|PATCH|DELETE)\s+(.+)\z/
231 raise ArgumentError unless request =~ /\A(GET|POST|PUT|PATCH|DELETE)\s+(.+)\z/
225 method, path = $1.downcase.to_sym, $2
232 method, path = $1.downcase.to_sym, $2
226
233
227 raise ArgumentError unless arg.values.first =~ /\A(.+)#(.+)\z/
234 raise ArgumentError unless arg.values.first =~ /\A(.+)#(.+)\z/
228 controller, action = $1, $2
235 controller, action = $1, $2
229
236
230 assert_routing(
237 assert_routing(
231 {:method => method, :path => path},
238 {:method => method, :path => path},
232 options.merge(:controller => controller, :action => action)
239 options.merge(:controller => controller, :action => action)
233 )
240 )
234 end
241 end
235 end
242 end
236
243
237 class IntegrationTest < ActionDispatch::IntegrationTest
244 class IntegrationTest < ActionDispatch::IntegrationTest
238 def log_user(login, password)
245 def log_user(login, password)
239 User.anonymous
246 User.anonymous
240 get "/login"
247 get "/login"
241 assert_equal nil, session[:user_id]
248 assert_equal nil, session[:user_id]
242 assert_response :success
249 assert_response :success
243 assert_template "account/login"
250 assert_template "account/login"
244 post "/login", :username => login, :password => password
251 post "/login", :username => login, :password => password
245 assert_equal login, User.find(session[:user_id]).login
252 assert_equal login, User.find(session[:user_id]).login
246 end
253 end
247
254
248 def credentials(user, password=nil)
255 def credentials(user, password=nil)
249 {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
256 {'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials(user, password || user)}
250 end
257 end
251 end
258 end
252
259
253 module ApiTest
260 module ApiTest
254 API_FORMATS = %w(json xml).freeze
261 API_FORMATS = %w(json xml).freeze
255
262
256 # Base class for API tests
263 # Base class for API tests
257 class Base < Redmine::IntegrationTest
264 class Base < Redmine::IntegrationTest
258 def setup
265 def setup
259 Setting.rest_api_enabled = '1'
266 Setting.rest_api_enabled = '1'
260 end
267 end
261
268
262 def teardown
269 def teardown
263 Setting.rest_api_enabled = '0'
270 Setting.rest_api_enabled = '0'
264 end
271 end
265 end
272 end
266
273
267 class Routing < Redmine::RoutingTest
274 class Routing < Redmine::RoutingTest
268 def should_route(arg)
275 def should_route(arg)
269 arg = arg.dup
276 arg = arg.dup
270 request = arg.keys.detect {|key| key.is_a?(String)}
277 request = arg.keys.detect {|key| key.is_a?(String)}
271 raise ArgumentError unless request
278 raise ArgumentError unless request
272 options = arg.slice!(request)
279 options = arg.slice!(request)
273
280
274 API_FORMATS.each do |format|
281 API_FORMATS.each do |format|
275 format_request = request.sub /$/, ".#{format}"
282 format_request = request.sub /$/, ".#{format}"
276 super options.merge(format_request => arg[request], :format => format)
283 super options.merge(format_request => arg[request], :format => format)
277 end
284 end
278 end
285 end
279 end
286 end
280 end
287 end
281 end
288 end
General Comments 0
You need to be logged in to leave comments. Login now