Compare commits
43
Commits
2.3.2
...
2.3-stable
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ce399b0fb | ||
|
|
e143f01e84 | ||
|
|
75e90593e0 | ||
|
|
daf2d54f27 | ||
|
|
8849727bd9 | ||
|
|
c4eb7c380e | ||
|
|
4deca5976e | ||
|
|
8a046027e5 | ||
|
|
711a8aa09b | ||
|
|
7ec18933e0 | ||
|
|
0a25ee385f | ||
|
|
79f90dfba5 | ||
|
|
2b53422d1d | ||
|
|
77ad962132 | ||
|
|
7bfb4759e7 | ||
|
|
9d3377c92c | ||
|
|
55a1869b86 | ||
|
|
bcae879091 | ||
|
|
2c44829509 | ||
|
|
d259dd2dd5 | ||
|
|
ddc016d81d | ||
|
|
e7c82e3934 | ||
|
|
e503f41f6f | ||
|
|
cd67243de5 | ||
|
|
b0c3b7a574 | ||
|
|
9a67caf248 | ||
|
|
67ee8653bd | ||
|
|
36978279c3 | ||
|
|
d155392b3c | ||
|
|
dc98cec17f | ||
|
|
e1e006f09e | ||
|
|
e8757fec2b | ||
|
|
591922c365 | ||
|
|
5eeca35317 | ||
|
|
2de51892ee | ||
|
|
3fe5e3bb6f | ||
|
|
bbf3ffe0aa | ||
|
|
b724eb4fec | ||
|
|
493119e795 | ||
|
|
f1b6b4ef33 | ||
|
|
ce002ee3df | ||
|
|
eb7862445c | ||
|
|
b31b5328e4 |
@@ -14,7 +14,7 @@ end
|
|||||||
|
|
||||||
# Optional gem for OpenID authentication
|
# Optional gem for OpenID authentication
|
||||||
group :openid do
|
group :openid do
|
||||||
gem "ruby-openid", "~> 2.1.4", :require => "openid"
|
gem "ruby-openid", "~> 2.3.0", :require => "openid"
|
||||||
gem "rack-openid"
|
gem "rack-openid"
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ end
|
|||||||
platforms :jruby do
|
platforms :jruby do
|
||||||
# jruby-openssl is bundled with JRuby 1.7.0
|
# jruby-openssl is bundled with JRuby 1.7.0
|
||||||
gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
|
gem "jruby-openssl" if Object.const_defined?(:JRUBY_VERSION) && JRUBY_VERSION < '1.7.0'
|
||||||
gem "activerecord-jdbc-adapter", "1.2.5"
|
gem "activerecord-jdbc-adapter", "~> 1.2.6"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Include database gems for the adapters found in the database
|
# Include database gems for the adapters found in the database
|
||||||
@@ -81,6 +81,7 @@ group :test do
|
|||||||
gem "mocha", "~> 0.13.3"
|
gem "mocha", "~> 0.13.3"
|
||||||
gem 'capybara', '~> 2.0.0'
|
gem 'capybara', '~> 2.0.0'
|
||||||
gem 'nokogiri', '< 1.6.0'
|
gem 'nokogiri', '< 1.6.0'
|
||||||
|
gem 'selenium-webdriver', '2.35.1'
|
||||||
end
|
end
|
||||||
|
|
||||||
local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
|
local_gemfile = File.join(File.dirname(__FILE__), "Gemfile.local")
|
||||||
|
|||||||
@@ -43,10 +43,10 @@ class TimelogController < ApplicationController
|
|||||||
|
|
||||||
def index
|
def index
|
||||||
@query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_')
|
@query = TimeEntryQuery.build_from_params(params, :project => @project, :name => '_')
|
||||||
scope = time_entry_scope
|
|
||||||
|
|
||||||
sort_init(@query.sort_criteria.empty? ? [['spent_on', 'desc']] : @query.sort_criteria)
|
sort_init(@query.sort_criteria.empty? ? [['spent_on', 'desc']] : @query.sort_criteria)
|
||||||
sort_update(@query.sortable_columns)
|
sort_update(@query.sortable_columns)
|
||||||
|
scope = time_entry_scope(:order => sort_clause)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html {
|
format.html {
|
||||||
@@ -55,7 +55,6 @@ class TimelogController < ApplicationController
|
|||||||
@entry_pages = Paginator.new @entry_count, per_page_option, params['page']
|
@entry_pages = Paginator.new @entry_count, per_page_option, params['page']
|
||||||
@entries = scope.all(
|
@entries = scope.all(
|
||||||
:include => [:project, :activity, :user, {:issue => :tracker}],
|
:include => [:project, :activity, :user, {:issue => :tracker}],
|
||||||
:order => sort_clause,
|
|
||||||
:limit => @entry_pages.per_page,
|
:limit => @entry_pages.per_page,
|
||||||
:offset => @entry_pages.offset
|
:offset => @entry_pages.offset
|
||||||
)
|
)
|
||||||
@@ -68,15 +67,13 @@ class TimelogController < ApplicationController
|
|||||||
@offset, @limit = api_offset_and_limit
|
@offset, @limit = api_offset_and_limit
|
||||||
@entries = scope.all(
|
@entries = scope.all(
|
||||||
:include => [:project, :activity, :user, {:issue => :tracker}],
|
:include => [:project, :activity, :user, {:issue => :tracker}],
|
||||||
:order => sort_clause,
|
|
||||||
:limit => @limit,
|
:limit => @limit,
|
||||||
:offset => @offset
|
:offset => @offset
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
format.atom {
|
format.atom {
|
||||||
entries = scope.all(
|
entries = scope.reorder("#{TimeEntry.table_name}.created_on DESC").all(
|
||||||
:include => [:project, :activity, :user, {:issue => :tracker}],
|
:include => [:project, :activity, :user, {:issue => :tracker}],
|
||||||
:order => "#{TimeEntry.table_name}.created_on DESC",
|
|
||||||
:limit => Setting.feeds_limit.to_i
|
:limit => Setting.feeds_limit.to_i
|
||||||
)
|
)
|
||||||
render_feed(entries, :title => l(:label_spent_time))
|
render_feed(entries, :title => l(:label_spent_time))
|
||||||
@@ -84,8 +81,7 @@ class TimelogController < ApplicationController
|
|||||||
format.csv {
|
format.csv {
|
||||||
# Export all entries
|
# Export all entries
|
||||||
@entries = scope.all(
|
@entries = scope.all(
|
||||||
:include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}],
|
:include => [:project, :activity, :user, {:issue => [:tracker, :assigned_to, :priority]}]
|
||||||
:order => sort_clause
|
|
||||||
)
|
)
|
||||||
send_data(query_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'timelog.csv')
|
send_data(query_to_csv(@entries, @query, params), :type => 'text/csv; header=present', :filename => 'timelog.csv')
|
||||||
}
|
}
|
||||||
@@ -295,12 +291,10 @@ private
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Returns the TimeEntry scope for index and report actions
|
# Returns the TimeEntry scope for index and report actions
|
||||||
def time_entry_scope
|
def time_entry_scope(options={})
|
||||||
scope = TimeEntry.visible.where(@query.statement)
|
scope = @query.results_scope(options)
|
||||||
if @issue
|
if @issue
|
||||||
scope = scope.on_issue(@issue)
|
scope = scope.on_issue(@issue)
|
||||||
elsif @project
|
|
||||||
scope = scope.on_project(@project, Setting.display_subprojects_issues?)
|
|
||||||
end
|
end
|
||||||
scope
|
scope
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -214,6 +214,28 @@ module IssuesHelper
|
|||||||
out
|
out
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def email_issue_attributes(issue)
|
||||||
|
items = []
|
||||||
|
%w(author status priority assigned_to category fixed_version).each do |attribute|
|
||||||
|
unless issue.disabled_core_fields.include?(attribute+"_id")
|
||||||
|
items << "#{l("field_#{attribute}")}: #{issue.send attribute}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
issue.custom_field_values.each do |value|
|
||||||
|
items << "#{value.custom_field.name}: #{show_value(value)}"
|
||||||
|
end
|
||||||
|
items
|
||||||
|
end
|
||||||
|
|
||||||
|
def render_email_issue_attributes(issue, html=false)
|
||||||
|
items = email_issue_attributes(issue)
|
||||||
|
if html
|
||||||
|
content_tag('ul', items.map{|s| content_tag('li', s)}.join("\n").html_safe)
|
||||||
|
else
|
||||||
|
items.map{|s| "* #{s}"}.join("\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Returns the textual representation of a journal details
|
# Returns the textual representation of a journal details
|
||||||
# as an array of strings
|
# as an array of strings
|
||||||
def details_to_strings(details, no_html=false, options={})
|
def details_to_strings(details, no_html=false, options={})
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ module ReportsHelper
|
|||||||
data.each { |row|
|
data.each { |row|
|
||||||
match = 1
|
match = 1
|
||||||
criteria.each { |k, v|
|
criteria.each { |k, v|
|
||||||
match = 0 unless (row[k].to_s == v.to_s) || (k == 'closed' && row[k] == (v == 0 ? "f" : "t"))
|
match = 0 unless (row[k].to_s == v.to_s) || (k == 'closed' && (v == 0 ? ['f', false] : ['t', true]).include?(row[k]))
|
||||||
} unless criteria.nil?
|
} unless criteria.nil?
|
||||||
a = a + row["total"].to_i if match == 1
|
a = a + row["total"].to_i if match == 1
|
||||||
} unless data.nil?
|
} unless data.nil?
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ class Attachment < ActiveRecord::Base
|
|||||||
if @temp_file && (@temp_file.size > 0)
|
if @temp_file && (@temp_file.size > 0)
|
||||||
self.disk_directory = target_directory
|
self.disk_directory = target_directory
|
||||||
self.disk_filename = Attachment.disk_filename(filename, disk_directory)
|
self.disk_filename = Attachment.disk_filename(filename, disk_directory)
|
||||||
logger.info("Saving attachment '#{self.diskfile}' (#{@temp_file.size} bytes)")
|
logger.info("Saving attachment '#{self.diskfile}' (#{@temp_file.size} bytes)") if logger
|
||||||
path = File.dirname(diskfile)
|
path = File.dirname(diskfile)
|
||||||
unless File.directory?(path)
|
unless File.directory?(path)
|
||||||
FileUtils.mkdir_p(path)
|
FileUtils.mkdir_p(path)
|
||||||
|
|||||||
+9
-4
@@ -106,10 +106,10 @@ class Issue < ActiveRecord::Base
|
|||||||
when 'all'
|
when 'all'
|
||||||
nil
|
nil
|
||||||
when 'default'
|
when 'default'
|
||||||
user_ids = [user.id] + user.groups.map(&:id)
|
user_ids = [user.id] + user.groups.map(&:id).compact
|
||||||
"(#{table_name}.is_private = #{connection.quoted_false} OR #{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
|
"(#{table_name}.is_private = #{connection.quoted_false} OR #{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
|
||||||
when 'own'
|
when 'own'
|
||||||
user_ids = [user.id] + user.groups.map(&:id)
|
user_ids = [user.id] + user.groups.map(&:id).compact
|
||||||
"(#{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
|
"(#{table_name}.author_id = #{user.id} OR #{table_name}.assigned_to_id IN (#{user_ids.join(',')}))"
|
||||||
else
|
else
|
||||||
'1=0'
|
'1=0'
|
||||||
@@ -745,11 +745,15 @@ class Issue < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
initial_status ||= status
|
initial_status ||= status
|
||||||
|
|
||||||
|
initial_assigned_to_id = assigned_to_id_changed? ? assigned_to_id_was : assigned_to_id
|
||||||
|
assignee_transitions_allowed = initial_assigned_to_id.present? &&
|
||||||
|
(user.id == initial_assigned_to_id || user.group_ids.include?(initial_assigned_to_id))
|
||||||
|
|
||||||
statuses = initial_status.find_new_statuses_allowed_to(
|
statuses = initial_status.find_new_statuses_allowed_to(
|
||||||
user.admin ? Role.all : user.roles_for_project(project),
|
user.admin ? Role.all : user.roles_for_project(project),
|
||||||
tracker,
|
tracker,
|
||||||
author == user,
|
author == user,
|
||||||
assigned_to_id_changed? ? assigned_to_id_was == user.id : assigned_to_id == user.id
|
assignee_transitions_allowed
|
||||||
)
|
)
|
||||||
statuses << initial_status unless statuses.empty?
|
statuses << initial_status unless statuses.empty?
|
||||||
statuses << IssueStatus.default if include_default
|
statuses << IssueStatus.default if include_default
|
||||||
@@ -1333,7 +1337,8 @@ class Issue < ActiveRecord::Base
|
|||||||
if average == 0
|
if average == 0
|
||||||
average = 1
|
average = 1
|
||||||
end
|
end
|
||||||
done = p.leaves.sum("COALESCE(estimated_hours, #{average}) * (CASE WHEN is_closed = #{connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)", :joins => :status).to_f
|
done = p.leaves.sum("COALESCE(CASE WHEN estimated_hours > 0 THEN estimated_hours ELSE NULL END, #{average}) " +
|
||||||
|
"* (CASE WHEN is_closed = #{connection.quoted_true} THEN 100 ELSE COALESCE(done_ratio, 0) END)", :joins => :status).to_f
|
||||||
progress = done / (average * leaves_count)
|
progress = done / (average * leaves_count)
|
||||||
p.done_ratio = progress.round
|
p.done_ratio = progress.round
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -393,10 +393,9 @@ class IssueQuery < Query
|
|||||||
|
|
||||||
if relation_options[:sym] == field && !options[:reverse]
|
if relation_options[:sym] == field && !options[:reverse]
|
||||||
sqls = [sql, sql_for_relations(field, operator, value, :reverse => true)]
|
sqls = [sql, sql_for_relations(field, operator, value, :reverse => true)]
|
||||||
sqls.join(["!", "!*", "!p"].include?(operator) ? " AND " : " OR ")
|
sql = sqls.join(["!", "!*", "!p"].include?(operator) ? " AND " : " OR ")
|
||||||
else
|
|
||||||
sql
|
|
||||||
end
|
end
|
||||||
|
"(#{sql})"
|
||||||
end
|
end
|
||||||
|
|
||||||
IssueRelation::TYPES.keys.each do |relation_type|
|
IssueRelation::TYPES.keys.each do |relation_type|
|
||||||
|
|||||||
@@ -100,6 +100,15 @@ class TimeEntryQuery < Query
|
|||||||
@default_columns_names ||= [:project, :spent_on, :user, :activity, :issue, :comments, :hours]
|
@default_columns_names ||= [:project, :spent_on, :user, :activity, :issue, :comments, :hours]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def results_scope(options={})
|
||||||
|
order_option = [group_by_sort_order, options[:order]].flatten.reject(&:blank?)
|
||||||
|
|
||||||
|
TimeEntry.visible.
|
||||||
|
where(statement).
|
||||||
|
order(order_option).
|
||||||
|
joins(joins_for_order_statement(order_option.join(',')))
|
||||||
|
end
|
||||||
|
|
||||||
# Accepts :from/:to params as shortcut filters
|
# Accepts :from/:to params as shortcut filters
|
||||||
def build_from_params(params)
|
def build_from_params(params)
|
||||||
super
|
super
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class UserPreference < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def [](attr_name)
|
def [](attr_name)
|
||||||
if attribute_present? attr_name
|
if has_attribute? attr_name
|
||||||
super
|
super
|
||||||
else
|
else
|
||||||
others ? others[attr_name] : nil
|
others ? others[attr_name] : nil
|
||||||
@@ -41,7 +41,7 @@ class UserPreference < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def []=(attr_name, value)
|
def []=(attr_name, value)
|
||||||
if attribute_present? attr_name
|
if has_attribute? attr_name
|
||||||
super
|
super
|
||||||
else
|
else
|
||||||
h = (read_attribute(:others) || {}).dup
|
h = (read_attribute(:others) || {}).dup
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
<h1><%= link_to(h("#{issue.tracker.name} ##{issue.id}: #{issue.subject}"), issue_url) %></h1>
|
<h1><%= link_to(h("#{issue.tracker.name} ##{issue.id}: #{issue.subject}"), issue_url) %></h1>
|
||||||
|
|
||||||
<ul>
|
<%= render_email_issue_attributes(issue, true) %>
|
||||||
<li><%=l(:field_author)%>: <%=h issue.author %></li>
|
|
||||||
<li><%=l(:field_status)%>: <%=h issue.status %></li>
|
|
||||||
<li><%=l(:field_priority)%>: <%=h issue.priority %></li>
|
|
||||||
<li><%=l(:field_assigned_to)%>: <%=h issue.assigned_to %></li>
|
|
||||||
<li><%=l(:field_category)%>: <%=h issue.category %></li>
|
|
||||||
<li><%=l(:field_fixed_version)%>: <%=h issue.fixed_version %></li>
|
|
||||||
<% issue.custom_field_values.each do |c| %>
|
|
||||||
<li><%=h c.custom_field.name %>: <%=h show_value(c) %></li>
|
|
||||||
<% end %>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<%= textilizable(issue, :description, :only_path => false) %>
|
<%= textilizable(issue, :description, :only_path => false) %>
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
<%= "#{issue.tracker.name} ##{issue.id}: #{issue.subject}" %>
|
<%= "#{issue.tracker.name} ##{issue.id}: #{issue.subject}" %>
|
||||||
<%= issue_url %>
|
<%= issue_url %>
|
||||||
|
|
||||||
* <%=l(:field_author)%>: <%= issue.author %>
|
<%= render_email_issue_attributes(issue) %>
|
||||||
* <%=l(:field_status)%>: <%= issue.status %>
|
|
||||||
* <%=l(:field_priority)%>: <%= issue.priority %>
|
|
||||||
* <%=l(:field_assigned_to)%>: <%= issue.assigned_to %>
|
|
||||||
* <%=l(:field_category)%>: <%= issue.category %>
|
|
||||||
* <%=l(:field_fixed_version)%>: <%= issue.fixed_version %>
|
|
||||||
<% issue.custom_field_values.each do |c| %>* <%= c.custom_field.name %>: <%= show_value(c) %>
|
|
||||||
<% end -%>
|
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
<%= issue.description %>
|
<%= issue.description %>
|
||||||
|
|||||||
@@ -19,8 +19,18 @@
|
|||||||
<tr class="bloc-<%= revision.nil? ? 0 : colors[revision.identifier || revision.revision] %>">
|
<tr class="bloc-<%= revision.nil? ? 0 : colors[revision.identifier || revision.revision] %>">
|
||||||
<th class="line-num" id="L<%= line_num %>"><a href="#L<%= line_num %>"><%= line_num %></a></th>
|
<th class="line-num" id="L<%= line_num %>"><a href="#L<%= line_num %>"><%= line_num %></a></th>
|
||||||
<td class="revision">
|
<td class="revision">
|
||||||
<%= (revision.identifier ? link_to_revision(revision, @repository) : format_revision(revision)) if revision && revision != previous_revision %></td>
|
<% if revision && revision != previous_revision %>
|
||||||
<td class="author"><%= h(revision.author.to_s.split('<').first) if revision && revision != previous_revision %></td>
|
<%= revision.identifier ?
|
||||||
|
link_to_revision(revision, @repository) : format_revision(revision) %>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
|
<td class="author">
|
||||||
|
<% if revision && revision != previous_revision %>
|
||||||
|
<% author = Redmine::CodesetUtil.to_utf8(revision.author.to_s,
|
||||||
|
@repository.repo_log_encoding) %>
|
||||||
|
<%= author.split('<').first %>
|
||||||
|
<% end %>
|
||||||
|
</td>
|
||||||
<td class="line-code"><pre><%= line.html_safe %></pre></td>
|
<td class="line-code"><pre><%= line.html_safe %></pre></td>
|
||||||
</tr>
|
</tr>
|
||||||
<% line_num += 1; previous_revision = revision %>
|
<% line_num += 1; previous_revision = revision %>
|
||||||
|
|||||||
@@ -1118,8 +1118,8 @@ es:
|
|||||||
permission_edit_documents: Editar documentos
|
permission_edit_documents: Editar documentos
|
||||||
permission_delete_documents: Borrar documentos
|
permission_delete_documents: Borrar documentos
|
||||||
label_gantt_progress_line: Línea de progreso
|
label_gantt_progress_line: Línea de progreso
|
||||||
setting_jsonp_enabled: Enable JSONP support
|
setting_jsonp_enabled: Habilitar soporte de JSONP
|
||||||
field_inherit_members: Inherit members
|
field_inherit_members: Heredar miembros
|
||||||
field_closed_on: Closed
|
field_closed_on: Cerrada
|
||||||
setting_default_projects_tracker_ids: Default trackers for new projects
|
setting_default_projects_tracker_ids: Tipos de petición habilitados por defecto
|
||||||
label_total_time: Total
|
label_total_time: Total
|
||||||
|
|||||||
@@ -1045,8 +1045,8 @@
|
|||||||
label_attribute_of_assigned_to: Assignee's %{name}
|
label_attribute_of_assigned_to: Assignee's %{name}
|
||||||
label_attribute_of_fixed_version: Target version's %{name}
|
label_attribute_of_fixed_version: Target version's %{name}
|
||||||
label_copy_subtasks: Copy subtasks
|
label_copy_subtasks: Copy subtasks
|
||||||
label_copied_to: copied to
|
label_copied_to: kopiert til
|
||||||
label_copied_from: copied from
|
label_copied_from: kopiert fra
|
||||||
label_any_issues_in_project: any issues in project
|
label_any_issues_in_project: any issues in project
|
||||||
label_any_issues_not_in_project: any issues not in project
|
label_any_issues_not_in_project: any issues not in project
|
||||||
field_private_notes: Private notes
|
field_private_notes: Private notes
|
||||||
|
|||||||
@@ -1091,5 +1091,5 @@ pt:
|
|||||||
setting_jsonp_enabled: Activar suporte JSONP
|
setting_jsonp_enabled: Activar suporte JSONP
|
||||||
field_inherit_members: Herdar membros
|
field_inherit_members: Herdar membros
|
||||||
field_closed_on: Fechado
|
field_closed_on: Fechado
|
||||||
setting_default_projects_tracker_ids: Default trackers for new projects
|
setting_default_projects_tracker_ids: Tipo de tarefa padrão para novos projectos
|
||||||
label_total_time: Total
|
label_total_time: Total
|
||||||
|
|||||||
+10
-10
@@ -1080,17 +1080,17 @@ ru:
|
|||||||
label_between: между
|
label_between: между
|
||||||
setting_issue_group_assignment: Разрешить назначение задач группам пользователей
|
setting_issue_group_assignment: Разрешить назначение задач группам пользователей
|
||||||
label_diff: Разница(diff)
|
label_diff: Разница(diff)
|
||||||
text_git_repository_note: Repository is bare and local (e.g. /gitrepo, c:\gitrepo)
|
text_git_repository_note: Хранилище пустое и локальное (т.е. /gitrepo, c:\gitrepo)
|
||||||
description_query_sort_criteria_direction: Порядок сортировки
|
description_query_sort_criteria_direction: Порядок сортировки
|
||||||
description_project_scope: Search scope
|
description_project_scope: Область поиска
|
||||||
description_filter: Фильтр
|
description_filter: Фильтр
|
||||||
description_user_mail_notification: Mail notification settings
|
description_user_mail_notification: Настройки почтовых оповещений
|
||||||
description_date_from: Enter start date
|
description_date_from: Введите дату начала
|
||||||
description_message_content: Message content
|
description_message_content: Содержание сообщения
|
||||||
description_available_columns: Available Columns
|
description_available_columns: Доступные столбцы
|
||||||
description_date_range_interval: Choose range by selecting start and end date
|
description_date_range_interval: Выберите диапазон, установив дату начала и дату окончания
|
||||||
description_issue_category_reassign: Choose issue category
|
description_issue_category_reassign: Выберите категорию задачи
|
||||||
description_search: Searchfield
|
description_search: Поле поиска
|
||||||
description_notes: Примечания
|
description_notes: Примечания
|
||||||
description_date_range_list: Выберите диапазон из списка
|
description_date_range_list: Выберите диапазон из списка
|
||||||
description_choose_project: Проекты
|
description_choose_project: Проекты
|
||||||
@@ -1145,7 +1145,7 @@ ru:
|
|||||||
project_status_active: открытые
|
project_status_active: открытые
|
||||||
project_status_closed: закрытые
|
project_status_closed: закрытые
|
||||||
project_status_archived: архивированные
|
project_status_archived: архивированные
|
||||||
text_project_closed: Проект закрыт и находиться в режиме только для чтения.
|
text_project_closed: Проект закрыт и находится в режиме только для чтения.
|
||||||
notice_user_successful_create: Пользователь %{id} создан.
|
notice_user_successful_create: Пользователь %{id} создан.
|
||||||
field_core_fields: Стандартные поля
|
field_core_fields: Стандартные поля
|
||||||
field_timeout: Таймаут (в секундах)
|
field_timeout: Таймаут (в секундах)
|
||||||
|
|||||||
@@ -712,7 +712,7 @@
|
|||||||
label_nobody: 無名
|
label_nobody: 無名
|
||||||
label_next: 下一頁
|
label_next: 下一頁
|
||||||
label_previous: 上一頁
|
label_previous: 上一頁
|
||||||
label_used_by: Used by
|
label_used_by: 已使用專案
|
||||||
label_details: 明細
|
label_details: 明細
|
||||||
label_add_note: 加入一個新筆記
|
label_add_note: 加入一個新筆記
|
||||||
label_per_page: 每頁
|
label_per_page: 每頁
|
||||||
|
|||||||
+14
-15
@@ -1075,19 +1075,18 @@ zh:
|
|||||||
label_cross_project_hierarchy: 与项目继承层次共享
|
label_cross_project_hierarchy: 与项目继承层次共享
|
||||||
label_cross_project_system: 与所有项目共享
|
label_cross_project_system: 与所有项目共享
|
||||||
button_hide: 隐藏
|
button_hide: 隐藏
|
||||||
setting_non_working_week_days: Non-working days
|
setting_non_working_week_days: 非工作日
|
||||||
label_in_the_next_days: in the next
|
label_in_the_next_days: 在未来几天之内
|
||||||
label_in_the_past_days: in the past
|
label_in_the_past_days: 在过去几天之内
|
||||||
label_attribute_of_user: User's %{name}
|
label_attribute_of_user: 用户是 %{name}
|
||||||
text_turning_multiple_off: If you disable multiple values, multiple values will be
|
text_turning_multiple_off: 如果您停用多重值设定,重复的值将被移除,以使每个项目仅保留一个值
|
||||||
removed in order to preserve only one value per item.
|
label_attribute_of_issue: 问题是 %{name}
|
||||||
label_attribute_of_issue: Issue's %{name}
|
permission_add_documents: 添加文档
|
||||||
permission_add_documents: Add documents
|
permission_edit_documents: 编辑文档
|
||||||
permission_edit_documents: Edit documents
|
permission_delete_documents: 删除文档
|
||||||
permission_delete_documents: Delete documents
|
label_gantt_progress_line: 进度线
|
||||||
label_gantt_progress_line: Progress line
|
setting_jsonp_enabled: 启用JSONP支持
|
||||||
setting_jsonp_enabled: Enable JSONP support
|
field_inherit_members: 继承父项目成员
|
||||||
field_inherit_members: Inherit members
|
field_closed_on: 结束日期
|
||||||
field_closed_on: Closed
|
setting_default_projects_tracker_ids: 新建项目默认跟踪标签
|
||||||
setting_default_projects_tracker_ids: Default trackers for new projects
|
|
||||||
label_total_time: 合计
|
label_total_time: 合计
|
||||||
|
|||||||
@@ -4,6 +4,27 @@ Redmine - project management software
|
|||||||
Copyright (C) 2006-2013 Jean-Philippe Lang
|
Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||||
http://www.redmine.org/
|
http://www.redmine.org/
|
||||||
|
|
||||||
|
== 2013-09-14 v2.3.3
|
||||||
|
|
||||||
|
* Defect #13008: Usage of attribute_present? in UserPreference
|
||||||
|
* Defect #14340: Autocomplete fields rendering issue with alternate theme
|
||||||
|
* Defect #14366: Spent Time report sorting on custom fields causes error
|
||||||
|
* Defect #14369: Open/closed issue counts on issues summary are not displayed with SQLServer
|
||||||
|
* Defect #14401: Filtering issues on "related to" may ignore other filters
|
||||||
|
* Defect #14415: Spent time details and report should ignore 'Setting.display_subprojects_issues?' when 'Subproject' filter is enabled.
|
||||||
|
* Defect #14422: CVS root_url not recognized when connection string does not include port
|
||||||
|
* Defect #14447: Additional status transitions for assignees do not work if assigned to a group
|
||||||
|
* Defect #14511: warning: class variable access from toplevel on Ruby 2.0
|
||||||
|
* Defect #14562: diff of CJK (Chinese/Japanese/Korean) is broken on Ruby 1.8
|
||||||
|
* Defect #14584: Standard fields disabled for certain trackers still appear in email notifications
|
||||||
|
* Defect #14607: rake redmine:load_default_data Error
|
||||||
|
* Defect #14697: Wrong Russian translation in close project message
|
||||||
|
* Defect #14798: Wrong done_ratio calculation for parent with subtask having estimated_hours=0
|
||||||
|
* Patch #14485: Traditional Chinese translation for 2.3-stable
|
||||||
|
* Patch #14502: Russian translation for 2.3-stable
|
||||||
|
* Patch #14531: Spanish translations for 2.3.x
|
||||||
|
* Patch #14686: Portuguese translation for 2.3-stable
|
||||||
|
|
||||||
== 2013-07-14 v2.3.2
|
== 2013-07-14 v2.3.2
|
||||||
|
|
||||||
* Defect #9996: configuration.yml in documentation , but redmine ask me to create email.yml
|
* Defect #9996: configuration.yml in documentation , but redmine ask me to create email.yml
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
begin
|
begin
|
||||||
require 'zlib'
|
require 'zlib'
|
||||||
@@__have_zlib = true
|
|
||||||
rescue
|
rescue
|
||||||
@@__have_zlib = false
|
# Zlib not available
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'rexml/document'
|
require 'rexml/document'
|
||||||
@@ -211,7 +210,7 @@ module SVG
|
|||||||
@doc.write( data, 0 )
|
@doc.write( data, 0 )
|
||||||
|
|
||||||
if @config[:compress]
|
if @config[:compress]
|
||||||
if @@__have_zlib
|
if Object.const_defined?(:Zlib)
|
||||||
inp, out = IO.pipe
|
inp, out = IO.pipe
|
||||||
gz = Zlib::GzipWriter.new( out )
|
gz = Zlib::GzipWriter.new( out )
|
||||||
gz.write data
|
gz.write data
|
||||||
|
|||||||
@@ -2431,7 +2431,7 @@ class TCPDF
|
|||||||
out('1 0 obj');
|
out('1 0 obj');
|
||||||
out('<</Type /Pages');
|
out('<</Type /Pages');
|
||||||
kids='/Kids [';
|
kids='/Kids [';
|
||||||
0.upto(nb) do |i|
|
0.upto(nb - 1) do |i|
|
||||||
kids<<(3+2*i).to_s + ' 0 R ';
|
kids<<(3+2*i).to_s + ' 0 R ';
|
||||||
end
|
end
|
||||||
out(kids + ']');
|
out(kids + ']');
|
||||||
@@ -3103,7 +3103,7 @@ class TCPDF
|
|||||||
# is a stream object that contains the definition of the CMap
|
# is a stream object that contains the definition of the CMap
|
||||||
# (PDF Reference 1.3 chap. 5.9)
|
# (PDF Reference 1.3 chap. 5.9)
|
||||||
newobj();
|
newobj();
|
||||||
out('<</Length 383>>');
|
out('<</Length 345>>')
|
||||||
out('stream');
|
out('stream');
|
||||||
out('/CIDInit /ProcSet findresource begin');
|
out('/CIDInit /ProcSet findresource begin');
|
||||||
out('12 dict begin');
|
out('12 dict begin');
|
||||||
|
|||||||
@@ -335,7 +335,7 @@ module Redmine
|
|||||||
# :pserver:anonymous@foo.bar:/path => /path
|
# :pserver:anonymous@foo.bar:/path => /path
|
||||||
# :ext:cvsservername:/path => /path
|
# :ext:cvsservername:/path => /path
|
||||||
def root_url_path
|
def root_url_path
|
||||||
root_url.to_s.gsub(/^:.+:\d*/, '')
|
root_url.to_s.gsub(%r{^:.+?(?=/)}, '')
|
||||||
end
|
end
|
||||||
|
|
||||||
# convert a date/time into the CVS-format
|
# convert a date/time into the CVS-format
|
||||||
|
|||||||
@@ -333,7 +333,7 @@ module Redmine
|
|||||||
|
|
||||||
def annotate(path, identifier=nil)
|
def annotate(path, identifier=nil)
|
||||||
identifier = 'HEAD' if identifier.blank?
|
identifier = 'HEAD' if identifier.blank?
|
||||||
cmd_args = %w|blame|
|
cmd_args = %w|blame --encoding=UTF-8|
|
||||||
cmd_args << "-p" << identifier << "--" << scm_iconv(@path_encoding, 'UTF-8', path)
|
cmd_args << "-p" << identifier << "--" << scm_iconv(@path_encoding, 'UTF-8', path)
|
||||||
blame = Annotate.new
|
blame = Annotate.new
|
||||||
content = nil
|
content = nil
|
||||||
|
|||||||
@@ -205,12 +205,20 @@ module Redmine
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
ending = -1
|
ending = -1
|
||||||
while ending >= -(max - starting) && line_left[ending] == line_right[ending]
|
while ending >= -(max - starting) && (line_left[ending] == line_right[ending])
|
||||||
ending -= 1
|
ending -= 1
|
||||||
end
|
end
|
||||||
if (! "".respond_to?(:force_encoding)) && ending > (-1 * line_left.size)
|
if (! "".respond_to?(:force_encoding)) && ending > (-1 * line_left.size)
|
||||||
while line_left[ending].ord.between?(128, 191) && ending > -1
|
while line_left[ending].ord.between?(128, 255) && ending < -1
|
||||||
ending -= 1
|
if line_left[ending].ord.between?(128, 191)
|
||||||
|
if line_left[ending + 1].ord.between?(128, 191)
|
||||||
|
ending += 1
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
else
|
||||||
|
ending += 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
unless starting == 0 && ending == -1
|
unless starting == 0 && ending == -1
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module Redmine
|
|||||||
module VERSION #:nodoc:
|
module VERSION #:nodoc:
|
||||||
MAJOR = 2
|
MAJOR = 2
|
||||||
MINOR = 3
|
MINOR = 3
|
||||||
TINY = 2
|
TINY = 3
|
||||||
|
|
||||||
# Branch values:
|
# Branch values:
|
||||||
# * official release: nil
|
# * official release: nil
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ desc 'Load Redmine default configuration data. Language is chosen interactively
|
|||||||
|
|
||||||
namespace :redmine do
|
namespace :redmine do
|
||||||
task :load_default_data => :environment do
|
task :load_default_data => :environment do
|
||||||
|
require 'custom_field'
|
||||||
include Redmine::I18n
|
include Redmine::I18n
|
||||||
set_language_if_valid('en')
|
set_language_if_valid('en')
|
||||||
|
|
||||||
|
|||||||
@@ -503,10 +503,20 @@ task :migrate_from_mantis => :environment do
|
|||||||
# Make sure bugs can refer bugs in other projects
|
# Make sure bugs can refer bugs in other projects
|
||||||
Setting.cross_project_issue_relations = 1 if Setting.respond_to? 'cross_project_issue_relations'
|
Setting.cross_project_issue_relations = 1 if Setting.respond_to? 'cross_project_issue_relations'
|
||||||
|
|
||||||
# Turn off email notifications
|
old_notified_events = Setting.notified_events
|
||||||
Setting.notified_events = []
|
old_password_min_length = Setting.password_min_length
|
||||||
|
begin
|
||||||
|
# Turn off email notifications temporarily
|
||||||
|
Setting.notified_events = []
|
||||||
|
Setting.password_min_length = 4
|
||||||
|
# Run the migration
|
||||||
|
MantisMigrate.establish_connection db_params
|
||||||
|
MantisMigrate.migrate
|
||||||
|
ensure
|
||||||
|
# Restore previous settings
|
||||||
|
Setting.notified_events = old_notified_events
|
||||||
|
Setting.password_min_length = old_password_min_length
|
||||||
|
end
|
||||||
|
|
||||||
MantisMigrate.establish_connection db_params
|
|
||||||
MantisMigrate.migrate
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -245,8 +245,8 @@ namespace :redmine do
|
|||||||
if name_attr = TracSessionAttribute.find_by_sid_and_name(username, 'name')
|
if name_attr = TracSessionAttribute.find_by_sid_and_name(username, 'name')
|
||||||
name = name_attr.value
|
name = name_attr.value
|
||||||
end
|
end
|
||||||
name =~ (/(.*)(\s+\w+)?/)
|
name =~ (/(\w+)(\s+\w+)?/)
|
||||||
fn = $1.strip
|
fn = ($1 || "-").strip
|
||||||
ln = ($2 || '-').strip
|
ln = ($2 || '-').strip
|
||||||
|
|
||||||
u = User.new :mail => mail.gsub(/[^-@a-z0-9\.]/i, '-'),
|
u = User.new :mail => mail.gsub(/[^-@a-z0-9\.]/i, '-'),
|
||||||
@@ -762,10 +762,19 @@ namespace :redmine do
|
|||||||
prompt('Target project identifier') {|identifier| TracMigrate.target_project_identifier identifier}
|
prompt('Target project identifier') {|identifier| TracMigrate.target_project_identifier identifier}
|
||||||
puts
|
puts
|
||||||
|
|
||||||
# Turn off email notifications
|
old_notified_events = Setting.notified_events
|
||||||
Setting.notified_events = []
|
old_password_min_length = Setting.password_min_length
|
||||||
|
begin
|
||||||
TracMigrate.migrate
|
# Turn off email notifications temporarily
|
||||||
|
Setting.notified_events = []
|
||||||
|
Setting.password_min_length = 4
|
||||||
|
# Run the migration
|
||||||
|
TracMigrate.migrate
|
||||||
|
ensure
|
||||||
|
# Restore previous settings
|
||||||
|
Setting.notified_events = old_notified_events
|
||||||
|
Setting.password_min_length = old_password_min_length
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -575,7 +575,7 @@ table.members td.group { padding-left: 20px; background: url(../images/group.png
|
|||||||
input#principal_search, input#user_search {width:90%}
|
input#principal_search, input#user_search {width:90%}
|
||||||
|
|
||||||
input.autocomplete {
|
input.autocomplete {
|
||||||
background: #fff url(../images/magnifier.png) no-repeat 2px 50%; padding-left:20px;
|
background: #fff url(../images/magnifier.png) no-repeat 2px 50%; padding-left:20px !important;
|
||||||
border:1px solid #9EB1C2; border-radius:2px; height:1.5em;
|
border:1px solid #9EB1C2; border-radius:2px; height:1.5em;
|
||||||
}
|
}
|
||||||
input.autocomplete.ajax-loading {
|
input.autocomplete.ajax-loading {
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
--- a.txt 2013-07-27 06:03:49.133257759 +0900
|
||||||
|
+++ b.txt 2013-07-27 06:03:58.791221118 +0900
|
||||||
|
@@ -1,3 +1,3 @@
|
||||||
|
aaaa
|
||||||
|
-日本記
|
||||||
|
+日本娘
|
||||||
|
bbbb
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
--- a.txt 2013-07-27 04:20:45.973229414 +0900
|
||||||
|
+++ b.txt 2013-07-27 04:20:52.366228105 +0900
|
||||||
|
@@ -1,3 +1,3 @@
|
||||||
|
aaaa
|
||||||
|
-日本記
|
||||||
|
+日本誘
|
||||||
|
bbbb
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
--- a.txt 2013-07-27 05:52:11.415223830 +0900
|
||||||
|
+++ b.txt 2013-07-27 05:52:18.249190358 +0900
|
||||||
|
@@ -1,3 +1,3 @@
|
||||||
|
aaaa
|
||||||
|
-日本記ok
|
||||||
|
+日本誘ok
|
||||||
|
bbbb
|
||||||
Binary file not shown.
@@ -209,7 +209,7 @@ class ProjectsControllerTest < ActionController::TestCase
|
|||||||
assert_response :success
|
assert_response :success
|
||||||
project = assigns(:project)
|
project = assigns(:project)
|
||||||
assert_kind_of Project, project
|
assert_kind_of Project, project
|
||||||
assert_not_nil project.errors[:parent_id]
|
assert_not_equal [], project.errors[:parent_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#create by non-admin user with add_subprojects permission should create a project with a parent_id" do
|
test "#create by non-admin user with add_subprojects permission should create a project with a parent_id" do
|
||||||
@@ -244,7 +244,7 @@ class ProjectsControllerTest < ActionController::TestCase
|
|||||||
assert_response :success
|
assert_response :success
|
||||||
project = assigns(:project)
|
project = assigns(:project)
|
||||||
assert_kind_of Project, project
|
assert_kind_of Project, project
|
||||||
assert_not_nil project.errors[:parent_id]
|
assert_not_equal [], project.errors[:parent_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "#create by non-admin user with add_subprojects permission should fail with unauthorized parent_id" do
|
test "#create by non-admin user with add_subprojects permission should fail with unauthorized parent_id" do
|
||||||
@@ -265,7 +265,7 @@ class ProjectsControllerTest < ActionController::TestCase
|
|||||||
assert_response :success
|
assert_response :success
|
||||||
project = assigns(:project)
|
project = assigns(:project)
|
||||||
assert_kind_of Project, project
|
assert_kind_of Project, project
|
||||||
assert_not_nil project.errors[:parent_id]
|
assert_not_equal [], project.errors[:parent_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_create_subproject_with_inherit_members_should_inherit_members
|
def test_create_subproject_with_inherit_members_should_inherit_members
|
||||||
|
|||||||
@@ -54,6 +54,24 @@ class ReportsControllerTest < ActionController::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_get_issue_report_details_by_tracker_should_show_issue_count
|
||||||
|
Issue.delete_all
|
||||||
|
Issue.generate!(:tracker_id => 1)
|
||||||
|
Issue.generate!(:tracker_id => 1)
|
||||||
|
Issue.generate!(:tracker_id => 1, :status_id => 5)
|
||||||
|
Issue.generate!(:tracker_id => 2)
|
||||||
|
|
||||||
|
get :issue_report_details, :id => 1, :detail => 'tracker'
|
||||||
|
assert_select 'table.list tbody :nth-child(1)' do
|
||||||
|
assert_select 'td', :text => 'Bug'
|
||||||
|
assert_select ':nth-child(2)', :text => '2' # status:1
|
||||||
|
assert_select ':nth-child(3)', :text => '-' # status:2
|
||||||
|
assert_select ':nth-child(8)', :text => '2' # open
|
||||||
|
assert_select ':nth-child(9)', :text => '1' # closed
|
||||||
|
assert_select ':nth-child(10)', :text => '3' # total
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_get_issue_report_details_by_priority
|
def test_get_issue_report_details_by_priority
|
||||||
get :issue_report_details, :id => 1, :detail => 'priority'
|
get :issue_report_details, :id => 1, :detail => 'priority'
|
||||||
assert_equal IssuePriority.all.reverse, assigns(:rows)
|
assert_equal IssuePriority.all.reverse, assigns(:rows)
|
||||||
|
|||||||
@@ -23,17 +23,23 @@ class RepositoriesBazaarControllerTest < ActionController::TestCase
|
|||||||
fixtures :projects, :users, :roles, :members, :member_roles,
|
fixtures :projects, :users, :roles, :members, :member_roles,
|
||||||
:repositories, :enabled_modules
|
:repositories, :enabled_modules
|
||||||
|
|
||||||
REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository/trunk').to_s
|
REPOSITORY_PATH = Rails.root.join('tmp/test/bazaar_repository').to_s
|
||||||
|
REPOSITORY_PATH_TRUNK = File.join(REPOSITORY_PATH, "trunk")
|
||||||
PRJ_ID = 3
|
PRJ_ID = 3
|
||||||
|
CHAR_1_UTF8_HEX = "\xc3\x9c"
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
User.current = nil
|
User.current = nil
|
||||||
@project = Project.find(PRJ_ID)
|
@project = Project.find(PRJ_ID)
|
||||||
@repository = Repository::Bazaar.create(
|
@repository = Repository::Bazaar.create(
|
||||||
:project => @project,
|
:project => @project,
|
||||||
:url => REPOSITORY_PATH,
|
:url => REPOSITORY_PATH_TRUNK,
|
||||||
:log_encoding => 'UTF-8')
|
:log_encoding => 'UTF-8')
|
||||||
assert @repository
|
assert @repository
|
||||||
|
@char_1_utf8 = CHAR_1_UTF8_HEX.dup
|
||||||
|
if @char_1_utf8.respond_to?(:force_encoding)
|
||||||
|
@char_1_utf8.force_encoding('UTF-8')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if File.directory?(REPOSITORY_PATH)
|
if File.directory?(REPOSITORY_PATH)
|
||||||
@@ -137,26 +143,68 @@ class RepositoriesBazaarControllerTest < ActionController::TestCase
|
|||||||
:path => repository_path_hash(['doc-mkdir.txt'])[:param]
|
:path => repository_path_hash(['doc-mkdir.txt'])[:param]
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template 'annotate'
|
assert_template 'annotate'
|
||||||
assert_tag :tag => 'th', :content => '2',
|
assert_select "th.line-num", :text => '2' do
|
||||||
:sibling => {
|
assert_select "+ td.revision" do
|
||||||
:tag => 'td',
|
assert_select "a", :text => '3'
|
||||||
:child => {
|
assert_select "+ td.author", :text => "jsmith@" do
|
||||||
:tag => 'a',
|
assert_select "+ td",
|
||||||
:content => '3'
|
:text => "Main purpose:"
|
||||||
}
|
end
|
||||||
}
|
end
|
||||||
assert_tag :tag => 'th', :content => '2',
|
end
|
||||||
:sibling => { :tag => 'td', :content => /jsmith/ }
|
end
|
||||||
assert_tag :tag => 'th', :content => '2',
|
|
||||||
:sibling => {
|
def test_annotate_author_escaping
|
||||||
:tag => 'td',
|
repository = Repository::Bazaar.create(
|
||||||
:child => {
|
:project => @project,
|
||||||
:tag => 'a',
|
:url => File.join(REPOSITORY_PATH, "author_escaping"),
|
||||||
:content => '3'
|
:identifier => 'author_escaping',
|
||||||
}
|
:log_encoding => 'UTF-8')
|
||||||
}
|
assert repository
|
||||||
assert_tag :tag => 'th', :content => '2',
|
get :annotate, :id => PRJ_ID, :repository_id => 'author_escaping',
|
||||||
:sibling => { :tag => 'td', :content => /Main purpose/ }
|
:path => repository_path_hash(['author-escaping-test.txt'])[:param]
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'annotate'
|
||||||
|
assert_select "th.line-num", :text => '1' do
|
||||||
|
assert_select "+ td.revision" do
|
||||||
|
assert_select "a", :text => '2'
|
||||||
|
assert_select "+ td.author", :text => "test &" do
|
||||||
|
assert_select "+ td",
|
||||||
|
:text => "author escaping test"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if REPOSITORY_PATH.respond_to?(:force_encoding)
|
||||||
|
def test_annotate_author_non_ascii
|
||||||
|
log_encoding = nil
|
||||||
|
if Encoding.locale_charmap == "UTF-8" ||
|
||||||
|
Encoding.locale_charmap == "ISO-8859-1"
|
||||||
|
log_encoding = Encoding.locale_charmap
|
||||||
|
end
|
||||||
|
unless log_encoding.nil?
|
||||||
|
repository = Repository::Bazaar.create(
|
||||||
|
:project => @project,
|
||||||
|
:url => File.join(REPOSITORY_PATH, "author_non_ascii"),
|
||||||
|
:identifier => 'author_non_ascii',
|
||||||
|
:log_encoding => log_encoding)
|
||||||
|
assert repository
|
||||||
|
get :annotate, :id => PRJ_ID, :repository_id => 'author_non_ascii',
|
||||||
|
:path => repository_path_hash(['author-non-ascii-test.txt'])[:param]
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'annotate'
|
||||||
|
assert_select "th.line-num", :text => '1' do
|
||||||
|
assert_select "+ td.revision" do
|
||||||
|
assert_select "a", :text => '2'
|
||||||
|
assert_select "+ td.author", :text => "test #{@char_1_utf8}" do
|
||||||
|
assert_select "+ td",
|
||||||
|
:text => "author non ASCII test"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_destroy_valid_repository
|
def test_destroy_valid_repository
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
|
REPOSITORY_PATH.gsub!(/\//, "\\") if Redmine::Platform.mswin?
|
||||||
PRJ_ID = 3
|
PRJ_ID = 3
|
||||||
CHAR_1_HEX = "\xc3\x9c"
|
CHAR_1_HEX = "\xc3\x9c"
|
||||||
|
FELIX_HEX = "Felix Sch\xC3\xA4fer"
|
||||||
NUM_REV = 28
|
NUM_REV = 28
|
||||||
|
|
||||||
## Git, Mercurial and CVS path encodings are binary.
|
## Git, Mercurial and CVS path encodings are binary.
|
||||||
@@ -50,8 +51,10 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
)
|
)
|
||||||
assert @repository
|
assert @repository
|
||||||
@char_1 = CHAR_1_HEX.dup
|
@char_1 = CHAR_1_HEX.dup
|
||||||
|
@felix_utf8 = FELIX_HEX.dup
|
||||||
if @char_1.respond_to?(:force_encoding)
|
if @char_1.respond_to?(:force_encoding)
|
||||||
@char_1.force_encoding('UTF-8')
|
@char_1.force_encoding('UTF-8')
|
||||||
|
@felix_utf8.force_encoding('UTF-8')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -532,11 +535,32 @@ class RepositoriesGitControllerTest < ActionController::TestCase
|
|||||||
get :annotate, :id => PRJ_ID,
|
get :annotate, :id => PRJ_ID,
|
||||||
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
|
:path => repository_path_hash(['latin-1-dir', "test-#{@char_1}.txt"])[:param],
|
||||||
:rev => r1
|
:rev => r1
|
||||||
assert_tag :tag => 'th',
|
assert_select "th.line-num", :text => '1' do
|
||||||
:content => '1',
|
assert_select "+ td.revision" do
|
||||||
:attributes => { :class => 'line-num' },
|
assert_select "a", :text => '57ca437c'
|
||||||
:sibling => { :tag => 'td',
|
assert_select "+ td.author", :text => "jsmith" do
|
||||||
:content => /test-#{@char_1}.txt/ }
|
assert_select "+ td",
|
||||||
|
:text => "test-#{@char_1}.txt"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_annotate_latin_1_author
|
||||||
|
['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', '83ca5fd546063a'].each do |r1|
|
||||||
|
get :annotate, :id => PRJ_ID,
|
||||||
|
:path => repository_path_hash([" filename with a leading space.txt "])[:param],
|
||||||
|
:rev => r1
|
||||||
|
assert_select "th.line-num", :text => '1' do
|
||||||
|
assert_select "+ td.revision" do
|
||||||
|
assert_select "a", :text => '83ca5fd5'
|
||||||
|
assert_select "+ td.author", :text => @felix_utf8 do
|
||||||
|
assert_select "+ td",
|
||||||
|
:text => "And this is a file with a leading and trailing space..."
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -432,30 +432,15 @@ class RepositoriesMercurialControllerTest < ActionController::TestCase
|
|||||||
:rev => r1
|
:rev => r1
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_template 'annotate'
|
assert_template 'annotate'
|
||||||
assert_tag :tag => 'th',
|
assert_select "th.line-num", :text => '1' do
|
||||||
:content => '1',
|
assert_select "+ td.revision" do
|
||||||
:attributes => { :class => 'line-num' },
|
assert_select "a", :text => '20:709858aafd1b'
|
||||||
:sibling =>
|
assert_select "+ td.author", :text => "jsmith" do
|
||||||
{
|
assert_select "+ td",
|
||||||
:tag => 'td',
|
:text => "Mercurial is a distributed version control system."
|
||||||
:attributes => { :class => 'revision' },
|
end
|
||||||
:child => { :tag => 'a', :content => '20:709858aafd1b' }
|
end
|
||||||
}
|
end
|
||||||
assert_tag :tag => 'th',
|
|
||||||
:content => '1',
|
|
||||||
:attributes => { :class => 'line-num' },
|
|
||||||
:sibling =>
|
|
||||||
{
|
|
||||||
:tag => 'td' ,
|
|
||||||
:content => 'jsmith' ,
|
|
||||||
:attributes => { :class => 'author' },
|
|
||||||
}
|
|
||||||
assert_tag :tag => 'th',
|
|
||||||
:content => '1',
|
|
||||||
:attributes => { :class => 'line-num' },
|
|
||||||
:sibling => { :tag => 'td',
|
|
||||||
:content => /Mercurial is a distributed version control system/ }
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -443,6 +443,28 @@ class TimelogControllerTest < ActionController::TestCase
|
|||||||
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
:attributes => {:action => "/projects/ecookbook/time_entries", :id => 'query_form'}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_index_with_display_subprojects_issues_to_false_should_not_include_subproject_entries
|
||||||
|
entry = TimeEntry.generate!(:project => Project.find(3))
|
||||||
|
|
||||||
|
with_settings :display_subprojects_issues => '0' do
|
||||||
|
get :index, :project_id => 'ecookbook'
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'index'
|
||||||
|
assert_not_include entry, assigns(:entries)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_index_with_display_subprojects_issues_to_false_and_subproject_filter_should_include_subproject_entries
|
||||||
|
entry = TimeEntry.generate!(:project => Project.find(3))
|
||||||
|
|
||||||
|
with_settings :display_subprojects_issues => '0' do
|
||||||
|
get :index, :project_id => 'ecookbook', :subproject_id => 3
|
||||||
|
assert_response :success
|
||||||
|
assert_template 'index'
|
||||||
|
assert_include entry, assigns(:entries)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_index_at_project_level_with_date_range
|
def test_index_at_project_level_with_date_range
|
||||||
get :index, :project_id => 'ecookbook',
|
get :index, :project_id => 'ecookbook',
|
||||||
:f => ['spent_on'],
|
:f => ['spent_on'],
|
||||||
@@ -540,6 +562,24 @@ class TimelogControllerTest < ActionController::TestCase
|
|||||||
assert_select 'td.issue_cf_2', :text => 'filter_on_issue_custom_field'
|
assert_select 'td.issue_cf_2', :text => 'filter_on_issue_custom_field'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_index_with_time_entry_custom_field_sorting
|
||||||
|
field = TimeEntryCustomField.generate!(:field_format => 'string', :name => 'String Field')
|
||||||
|
TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 1'})
|
||||||
|
TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 3'})
|
||||||
|
TimeEntry.generate!(:hours => 2.5, :custom_field_values => {field.id => 'CF Value 2'})
|
||||||
|
field_name = "cf_#{field.id}"
|
||||||
|
|
||||||
|
get :index, :c => ["hours", field_name], :sort => field_name
|
||||||
|
assert_response :success
|
||||||
|
assert_include field_name.to_sym, assigns(:query).column_names
|
||||||
|
assert_select "th a.sort", :text => 'String Field'
|
||||||
|
|
||||||
|
# Make sure that values are properly sorted
|
||||||
|
values = assigns(:entries).map {|e| e.custom_field_value(field)}.compact
|
||||||
|
assert_equal 3, values.size
|
||||||
|
assert_equal values.sort, values
|
||||||
|
end
|
||||||
|
|
||||||
def test_index_atom_feed
|
def test_index_atom_feed
|
||||||
get :index, :project_id => 1, :format => 'atom'
|
get :index, :project_id => 1, :format => 'atom'
|
||||||
assert_response :success
|
assert_response :success
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class AttachmentTest < ActiveSupport::TestCase
|
|||||||
def test_description_length_should_be_validated
|
def test_description_length_should_be_validated
|
||||||
a = Attachment.new(:description => 'a' * 300)
|
a = Attachment.new(:description => 'a' * 300)
|
||||||
assert !a.save
|
assert !a.save
|
||||||
assert_not_nil a.errors[:description]
|
assert_not_equal [], a.errors[:description]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_destroy
|
def test_destroy
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class IssueNestedSetTest < ActiveSupport::TestCase
|
|||||||
child = Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
|
child = Issue.new(:project_id => 2, :tracker_id => 1, :author_id => 1,
|
||||||
:subject => 'child', :parent_issue_id => issue.id)
|
:subject => 'child', :parent_issue_id => issue.id)
|
||||||
assert !child.save
|
assert !child.save
|
||||||
assert_not_nil child.errors[:parent_issue_id]
|
assert_not_equal [], child.errors[:parent_issue_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_move_a_root_to_child
|
def test_move_a_root_to_child
|
||||||
@@ -163,7 +163,7 @@ class IssueNestedSetTest < ActiveSupport::TestCase
|
|||||||
child.reload
|
child.reload
|
||||||
child.parent_issue_id = grandchild.id
|
child.parent_issue_id = grandchild.id
|
||||||
assert !child.save
|
assert !child.save
|
||||||
assert_not_nil child.errors[:parent_issue_id]
|
assert_not_equal [], child.errors[:parent_issue_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_destroy_should_destroy_children
|
def test_destroy_should_destroy_children
|
||||||
@@ -302,6 +302,17 @@ class IssueNestedSetTest < ActiveSupport::TestCase
|
|||||||
assert_equal (50 * 20 + 20 * 10) / 30, parent.reload.done_ratio
|
assert_equal (50 * 20 + 20 * 10) / 30, parent.reload.done_ratio
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_parent_done_ratio_with_child_estimate_to_0_should_reach_100
|
||||||
|
parent = Issue.generate!
|
||||||
|
issue1 = Issue.generate!(:parent_issue_id => parent.id)
|
||||||
|
issue2 = Issue.generate!(:parent_issue_id => parent.id, :estimated_hours => 0)
|
||||||
|
assert_equal 0, parent.reload.done_ratio
|
||||||
|
issue1.reload.update_attribute :status_id, 5
|
||||||
|
assert_equal 50, parent.reload.done_ratio
|
||||||
|
issue2.reload.update_attribute :status_id, 5
|
||||||
|
assert_equal 100, parent.reload.done_ratio
|
||||||
|
end
|
||||||
|
|
||||||
def test_parent_estimate_should_be_sum_of_leaves
|
def test_parent_estimate_should_be_sum_of_leaves
|
||||||
parent = Issue.generate!
|
parent = Issue.generate!
|
||||||
Issue.generate!(:estimated_hours => nil, :parent_issue_id => parent.id)
|
Issue.generate!(:estimated_hours => nil, :parent_issue_id => parent.id)
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class IssueRelationTest < ActiveSupport::TestCase
|
|||||||
:relation_type => IssueRelation::TYPE_PRECEDES
|
:relation_type => IssueRelation::TYPE_PRECEDES
|
||||||
)
|
)
|
||||||
assert !r.save
|
assert !r.save
|
||||||
assert_not_nil r.errors[:base]
|
assert_not_equal [], r.errors[:base]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_validates_circular_dependency_of_subtask
|
def test_validates_circular_dependency_of_subtask
|
||||||
@@ -165,6 +165,6 @@ class IssueRelationTest < ActiveSupport::TestCase
|
|||||||
:relation_type => IssueRelation::TYPE_BLOCKED
|
:relation_type => IssueRelation::TYPE_BLOCKED
|
||||||
)
|
)
|
||||||
assert !r.save
|
assert !r.save
|
||||||
assert_not_nil r.errors[:base]
|
assert_not_equal [], r.errors[:base]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+27
-7
@@ -469,7 +469,7 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
issue.tracker_id = 2
|
issue.tracker_id = 2
|
||||||
issue.subject = 'New subject'
|
issue.subject = 'New subject'
|
||||||
assert !issue.save
|
assert !issue.save
|
||||||
assert_not_nil issue.errors[:tracker_id]
|
assert_not_equal [], issue.errors[:tracker_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_category_based_assignment
|
def test_category_based_assignment
|
||||||
@@ -488,9 +488,9 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
|
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
|
||||||
:old_status_id => 1, :new_status_id => 3,
|
:old_status_id => 1, :new_status_id => 3,
|
||||||
:author => true, :assignee => false)
|
:author => true, :assignee => false)
|
||||||
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1, :old_status_id => 1,
|
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
|
||||||
:new_status_id => 4, :author => false,
|
:old_status_id => 1, :new_status_id => 4,
|
||||||
:assignee => true)
|
:author => false, :assignee => true)
|
||||||
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
|
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
|
||||||
:old_status_id => 1, :new_status_id => 5,
|
:old_status_id => 1, :new_status_id => 5,
|
||||||
:author => true, :assignee => true)
|
:author => true, :assignee => true)
|
||||||
@@ -516,6 +516,26 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
:project_id => 1, :author => user,
|
:project_id => 1, :author => user,
|
||||||
:assigned_to => user)
|
:assigned_to => user)
|
||||||
assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
|
assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
|
||||||
|
|
||||||
|
group = Group.generate!
|
||||||
|
group.users << user
|
||||||
|
issue = Issue.generate!(:tracker => tracker, :status => status,
|
||||||
|
:project_id => 1, :author => user,
|
||||||
|
:assigned_to => group)
|
||||||
|
assert_equal [1, 2, 3, 4, 5], issue.new_statuses_allowed_to(user).map(&:id)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_new_statuses_allowed_to_should_consider_group_assignment
|
||||||
|
WorkflowTransition.delete_all
|
||||||
|
WorkflowTransition.create!(:role_id => 1, :tracker_id => 1,
|
||||||
|
:old_status_id => 1, :new_status_id => 4,
|
||||||
|
:author => false, :assignee => true)
|
||||||
|
user = User.find(2)
|
||||||
|
group = Group.generate!
|
||||||
|
group.users << user
|
||||||
|
|
||||||
|
issue = Issue.generate!(:author_id => 1, :assigned_to => group)
|
||||||
|
assert_include 4, issue.new_statuses_allowed_to(user).map(&:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
|
def test_new_statuses_allowed_to_should_return_all_transitions_for_admin
|
||||||
@@ -1004,7 +1024,7 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
:status_id => 1, :fixed_version_id => 1,
|
:status_id => 1, :fixed_version_id => 1,
|
||||||
:subject => 'New issue')
|
:subject => 'New issue')
|
||||||
assert !issue.save
|
assert !issue.save
|
||||||
assert_not_nil issue.errors[:fixed_version_id]
|
assert_not_equal [], issue.errors[:fixed_version_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
|
def test_should_not_be_able_to_assign_a_new_issue_to_a_locked_version
|
||||||
@@ -1012,7 +1032,7 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
:status_id => 1, :fixed_version_id => 2,
|
:status_id => 1, :fixed_version_id => 2,
|
||||||
:subject => 'New issue')
|
:subject => 'New issue')
|
||||||
assert !issue.save
|
assert !issue.save
|
||||||
assert_not_nil issue.errors[:fixed_version_id]
|
assert_not_equal [], issue.errors[:fixed_version_id]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_should_be_able_to_assign_a_new_issue_to_an_open_version
|
def test_should_be_able_to_assign_a_new_issue_to_an_open_version
|
||||||
@@ -1033,7 +1053,7 @@ class IssueTest < ActiveSupport::TestCase
|
|||||||
issue = Issue.find(11)
|
issue = Issue.find(11)
|
||||||
issue.status_id = 1
|
issue.status_id = 1
|
||||||
assert !issue.save
|
assert !issue.save
|
||||||
assert_not_nil issue.errors[:base]
|
assert_not_equal [], issue.errors[:base]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
|
def test_should_be_able_to_reopen_and_reassign_an_issue_assigned_to_a_closed_version
|
||||||
|
|||||||
@@ -79,6 +79,22 @@ begin
|
|||||||
assert_equal "UTF-8", adpt2.path_encoding
|
assert_equal "UTF-8", adpt2.path_encoding
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_root_url_path
|
||||||
|
to_test = {
|
||||||
|
':pserver:cvs_user:cvs_password@123.456.789.123:9876/repo' => '/repo',
|
||||||
|
':pserver:cvs_user:cvs_password@123.456.789.123/repo' => '/repo',
|
||||||
|
':pserver:cvs_user:cvs_password@cvs_server:/repo' => '/repo',
|
||||||
|
':pserver:cvs_user:cvs_password@cvs_server:9876/repo' => '/repo',
|
||||||
|
':pserver:cvs_user:cvs_password@cvs_server/repo' => '/repo',
|
||||||
|
':pserver:cvs_user:cvs_password@cvs_server/path/repo' => '/path/repo',
|
||||||
|
':ext:cvsservername:/path' => '/path'
|
||||||
|
}
|
||||||
|
|
||||||
|
to_test.each do |string, expected|
|
||||||
|
assert_equal expected, Redmine::Scm::Adapters::CvsAdapter.new('foo', string).send(:root_url_path), "#{string} failed"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def test_scm_version_for(scm_command_version, version)
|
def test_scm_version_for(scm_command_version, version)
|
||||||
|
|||||||
@@ -61,8 +61,10 @@ begin
|
|||||||
)
|
)
|
||||||
assert @adapter
|
assert @adapter
|
||||||
@char_1 = CHAR_1_HEX.dup
|
@char_1 = CHAR_1_HEX.dup
|
||||||
|
@str_felix_hex = FELIX_HEX.dup
|
||||||
if @char_1.respond_to?(:force_encoding)
|
if @char_1.respond_to?(:force_encoding)
|
||||||
@char_1.force_encoding('UTF-8')
|
@char_1.force_encoding('UTF-8')
|
||||||
|
@str_felix_hex.force_encoding('ASCII-8BIT')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -396,14 +398,10 @@ begin
|
|||||||
def test_last_rev_with_spaces_in_filename
|
def test_last_rev_with_spaces_in_filename
|
||||||
last_rev = @adapter.lastrev("filemane with spaces.txt",
|
last_rev = @adapter.lastrev("filemane with spaces.txt",
|
||||||
"ed5bb786bbda2dee66a2d50faf51429dbc043a7b")
|
"ed5bb786bbda2dee66a2d50faf51429dbc043a7b")
|
||||||
str_felix_hex = FELIX_HEX.dup
|
|
||||||
last_rev_author = last_rev.author
|
last_rev_author = last_rev.author
|
||||||
if last_rev_author.respond_to?(:force_encoding)
|
|
||||||
str_felix_hex.force_encoding('ASCII-8BIT')
|
|
||||||
end
|
|
||||||
assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid
|
assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.scmid
|
||||||
assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier
|
assert_equal "ed5bb786bbda2dee66a2d50faf51429dbc043a7b", last_rev.identifier
|
||||||
assert_equal "#{str_felix_hex} <felix@fachschaften.org>",
|
assert_equal "#{@str_felix_hex} <felix@fachschaften.org>",
|
||||||
last_rev.author
|
last_rev.author
|
||||||
assert_equal "2010-09-18 19:59:46".to_time, last_rev.time
|
assert_equal "2010-09-18 19:59:46".to_time, last_rev.time
|
||||||
end
|
end
|
||||||
@@ -426,6 +424,19 @@ begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_latin_1_user_annotate
|
||||||
|
['83ca5fd546063a3c7dc2e568ba3355661a9e2b2c', '83ca5fd546063a'].each do |r1|
|
||||||
|
annotate = @adapter.annotate(" filename with a leading space.txt ", r1)
|
||||||
|
assert_kind_of Redmine::Scm::Adapters::Annotate, annotate
|
||||||
|
assert_equal 1, annotate.lines.size
|
||||||
|
assert_equal "And this is a file with a leading and trailing space...",
|
||||||
|
annotate.lines[0].strip
|
||||||
|
assert_equal "83ca5fd546063a3c7dc2e568ba3355661a9e2b2c",
|
||||||
|
annotate.revisions[0].identifier
|
||||||
|
assert_equal @str_felix_hex, annotate.revisions[0].author
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_entries_tag
|
def test_entries_tag
|
||||||
entries1 = @adapter.entries(nil, 'tag01.annotated',
|
entries1 = @adapter.entries(nil, 'tag01.annotated',
|
||||||
options = {:report_last_commit => true})
|
options = {:report_last_commit => true})
|
||||||
|
|||||||
@@ -308,6 +308,54 @@ DIFF
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_offset_range_japanese_3
|
||||||
|
# UTF-8 The 1st byte differs.
|
||||||
|
ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>"
|
||||||
|
ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
|
||||||
|
ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe5\xa8\x98</span>"
|
||||||
|
ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
|
||||||
|
with_settings :repositories_encodings => '' do
|
||||||
|
diff = Redmine::UnifiedDiff.new(
|
||||||
|
read_diff_fixture('issue-13644-3.diff'), :type => 'sbs')
|
||||||
|
assert_equal 1, diff.size
|
||||||
|
assert_equal 3, diff.first.size
|
||||||
|
assert_equal ja1, diff.first[1].html_line_left
|
||||||
|
assert_equal ja2, diff.first[1].html_line_right
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_offset_range_japanese_4
|
||||||
|
# UTF-8 The 2nd byte differs.
|
||||||
|
ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>"
|
||||||
|
ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
|
||||||
|
ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x98</span>"
|
||||||
|
ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
|
||||||
|
with_settings :repositories_encodings => '' do
|
||||||
|
diff = Redmine::UnifiedDiff.new(
|
||||||
|
read_diff_fixture('issue-13644-4.diff'), :type => 'sbs')
|
||||||
|
assert_equal 1, diff.size
|
||||||
|
assert_equal 3, diff.first.size
|
||||||
|
assert_equal ja1, diff.first[1].html_line_left
|
||||||
|
assert_equal ja2, diff.first[1].html_line_right
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_offset_range_japanese_5
|
||||||
|
# UTF-8 The 2nd byte differs.
|
||||||
|
ja1 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xa8\x98</span>ok"
|
||||||
|
ja1.force_encoding('UTF-8') if ja1.respond_to?(:force_encoding)
|
||||||
|
ja2 = "\xe6\x97\xa5\xe6\x9c\xac<span>\xe8\xaa\x98</span>ok"
|
||||||
|
ja2.force_encoding('UTF-8') if ja2.respond_to?(:force_encoding)
|
||||||
|
with_settings :repositories_encodings => '' do
|
||||||
|
diff = Redmine::UnifiedDiff.new(
|
||||||
|
read_diff_fixture('issue-13644-5.diff'), :type => 'sbs')
|
||||||
|
assert_equal 1, diff.size
|
||||||
|
assert_equal 3, diff.first.size
|
||||||
|
assert_equal ja1, diff.first[1].html_line_left
|
||||||
|
assert_equal ja2, diff.first[1].html_line_right
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def read_diff_fixture(filename)
|
def read_diff_fixture(filename)
|
||||||
|
|||||||
@@ -315,6 +315,29 @@ class MailerTest < ActiveSupport::TestCase
|
|||||||
assert !last_email.bcc.include?(user.mail)
|
assert !last_email.bcc.include?(user.mail)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_issue_add_should_include_enabled_fields
|
||||||
|
Setting.default_language = 'en'
|
||||||
|
issue = Issue.find(2)
|
||||||
|
assert Mailer.deliver_issue_add(issue)
|
||||||
|
assert_mail_body_match '* Target version: 1.0', last_email
|
||||||
|
assert_select_email do
|
||||||
|
assert_select 'li', :text => 'Target version: 1.0'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_issue_add_should_not_include_disabled_fields
|
||||||
|
Setting.default_language = 'en'
|
||||||
|
issue = Issue.find(2)
|
||||||
|
tracker = issue.tracker
|
||||||
|
tracker.core_fields -= ['fixed_version_id']
|
||||||
|
tracker.save!
|
||||||
|
assert Mailer.deliver_issue_add(issue)
|
||||||
|
assert_mail_body_no_match 'Target version', last_email
|
||||||
|
assert_select_email do
|
||||||
|
assert_select 'li', :text => /Target version/, :count => 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# test mailer methods for each language
|
# test mailer methods for each language
|
||||||
def test_issue_add
|
def test_issue_add
|
||||||
issue = Issue.find(1)
|
issue = Issue.find(1)
|
||||||
|
|||||||
@@ -746,6 +746,21 @@ class QueryTest < ActiveSupport::TestCase
|
|||||||
assert_equal [1, 2, 3], find_issues_with_query(query).map(&:id).sort
|
assert_equal [1, 2, 3], find_issues_with_query(query).map(&:id).sort
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_filter_on_relations_should_not_ignore_other_filter
|
||||||
|
issue = Issue.generate!
|
||||||
|
issue1 = Issue.generate!(:status_id => 1)
|
||||||
|
issue2 = Issue.generate!(:status_id => 2)
|
||||||
|
IssueRelation.create!(:relation_type => "relates", :issue_from => issue, :issue_to => issue1)
|
||||||
|
IssueRelation.create!(:relation_type => "relates", :issue_from => issue, :issue_to => issue2)
|
||||||
|
|
||||||
|
query = IssueQuery.new(:name => '_')
|
||||||
|
query.filters = {
|
||||||
|
"status_id" => {:operator => '=', :values => ['1']},
|
||||||
|
"relates" => {:operator => '=', :values => [issue.id.to_s]}
|
||||||
|
}
|
||||||
|
assert_equal [issue1], find_issues_with_query(query)
|
||||||
|
end
|
||||||
|
|
||||||
def test_statement_should_be_nil_with_no_filters
|
def test_statement_should_be_nil_with_no_filters
|
||||||
q = IssueQuery.new(:name => '_')
|
q = IssueQuery.new(:name => '_')
|
||||||
q.filters = {}
|
q.filters = {}
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ class UserPreferenceTest < ActiveSupport::TestCase
|
|||||||
assert_kind_of Hash, up.others
|
assert_kind_of Hash, up.others
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_others_should_be_blank_after_initialization
|
||||||
|
pref = User.new.pref
|
||||||
|
assert_equal({}, pref.others)
|
||||||
|
end
|
||||||
|
|
||||||
def test_reading_value_from_nil_others_hash
|
def test_reading_value_from_nil_others_hash
|
||||||
up = UserPreference.new(:user => User.new)
|
up = UserPreference.new(:user => User.new)
|
||||||
up.others = nil
|
up.others = nil
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ class UserTest < ActiveSupport::TestCase
|
|||||||
u = User.new
|
u = User.new
|
||||||
u.mail_notification = 'foo'
|
u.mail_notification = 'foo'
|
||||||
u.save
|
u.save
|
||||||
assert_not_nil u.errors[:mail_notification]
|
assert_not_equal [], u.errors[:mail_notification]
|
||||||
end
|
end
|
||||||
|
|
||||||
context "User#try_to_login" do
|
context "User#try_to_login" do
|
||||||
|
|||||||
Reference in New Issue
Block a user