+++ /dev/null
-# redMine - project management software
-# Copyright (C) 2006-2007 Jean-Philippe Lang
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-require 'uri'
-require 'cgi'
-
-class ApplicationController < ActionController::Base
- include Redmine::I18n
-
- # In case the cookie store secret changes
- rescue_from CGI::Session::CookieStore::TamperedWithCookie do |exception|
- render :text => 'Your session was invalid and has been reset. Please, reload this page.', :status => 500
- end
-
- layout 'base'
-
- before_filter :user_setup, :check_if_login_required, :set_localization
- filter_parameter_logging :password
-
- include Redmine::MenuManager::MenuController
- helper Redmine::MenuManager::MenuHelper
-
- REDMINE_SUPPORTED_SCM.each do |scm|
- require_dependency "repository/#{scm.underscore}"
- end
-
- def user_setup
- # Check the settings cache for each request
- Setting.check_cache
- # Find the current user
- User.current = find_current_user
- end
-
- # Returns the current user or nil if no user is logged in
- # and starts a session if needed
- def find_current_user
- if session[:user_id]
- # existing session
- (User.active.find(session[:user_id]) rescue nil)
- elsif cookies[:autologin] && Setting.autologin?
- # auto-login feature starts a new session
- user = User.try_to_autologin(cookies[:autologin])
- session[:user_id] = user.id if user
- user
- elsif params[:format] == 'atom' && params[:key] && accept_key_auth_actions.include?(params[:action])
- # RSS key authentication does not start a session
- User.find_by_rss_key(params[:key])
- end
- end
-
- # Sets the logged in user
- def logged_user=(user)
- if user && user.is_a?(User)
- User.current = user
- session[:user_id] = user.id
- else
- User.current = User.anonymous
- session[:user_id] = nil
- end
- end
-
- # check if login is globally required to access the application
- def check_if_login_required
- # no check needed if user is already logged in
- return true if User.current.logged?
- require_login if Setting.login_required?
- end
-
- def set_localization
- lang = nil
- if User.current.logged?
- lang = find_language(User.current.language)
- end
- if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE']
- accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.downcase
- if !accept_lang.blank?
- lang = find_language(accept_lang) || find_language(accept_lang.split('-').first)
- end
- end
- lang ||= Setting.default_language
- set_language_if_valid(lang)
- end
-
- def require_login
- if !User.current.logged?
- redirect_to :controller => "account", :action => "login", :back_url => url_for(params)
- return false
- end
- true
- end
-
- def require_admin
- return unless require_login
- if !User.current.admin?
- render_403
- return false
- end
- true
- end
-
- def deny_access
- User.current.logged? ? render_403 : require_login
- end
-
- # Authorize the user for the requested action
- def authorize(ctrl = params[:controller], action = params[:action], global = false)
- allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project, :global => global)
- allowed ? true : deny_access
- end
-
- # Authorize the user for the requested action outside a project
- def authorize_global(ctrl = params[:controller], action = params[:action], global = true)
- authorize(ctrl, action, global)
- end
-
- # make sure that the user is a member of the project (or admin) if project is private
- # used as a before_filter for actions that do not require any particular permission on the project
- def check_project_privacy
- if @project && @project.active?
- if @project.is_public? || User.current.member_of?(@project) || User.current.admin?
- true
- else
- User.current.logged? ? render_403 : require_login
- end
- else
- @project = nil
- render_404
- false
- end
- end
-
- def redirect_back_or_default(default)
- back_url = CGI.unescape(params[:back_url].to_s)
- if !back_url.blank?
- begin
- uri = URI.parse(back_url)
- # do not redirect user to another host or to the login or register page
- if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
- redirect_to(back_url) and return
- end
- rescue URI::InvalidURIError
- # redirect to default
- end
- end
- redirect_to default
- end
-
- def render_403
- @project = nil
- render :template => "common/403", :layout => !request.xhr?, :status => 403
- return false
- end
-
- def render_404
- render :template => "common/404", :layout => !request.xhr?, :status => 404
- return false
- end
-
- def render_error(msg)
- flash.now[:error] = msg
- render :text => '', :layout => !request.xhr?, :status => 500
- end
-
- def render_feed(items, options={})
- @items = items || []
- @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
- @items = @items.slice(0, Setting.feeds_limit.to_i)
- @title = options[:title] || Setting.app_title
- render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
- end
-
- def self.accept_key_auth(*actions)
- actions = actions.flatten.map(&:to_s)
- write_inheritable_attribute('accept_key_auth_actions', actions)
- end
-
- def accept_key_auth_actions
- self.class.read_inheritable_attribute('accept_key_auth_actions') || []
- end
-
- # TODO: move to model
- def attach_files(obj, attachments)
- attached = []
- unsaved = []
- if attachments && attachments.is_a?(Hash)
- attachments.each_value do |attachment|
- file = attachment['file']
- next unless file && file.size > 0
- a = Attachment.create(:container => obj,
- :file => file,
- :description => attachment['description'].to_s.strip,
- :author => User.current)
- a.new_record? ? (unsaved << a) : (attached << a)
- end
- if unsaved.any?
- flash[:warning] = l(:warning_attachments_not_saved, unsaved.size)
- end
- end
- attached
- end
-
- # Returns the number of objects that should be displayed
- # on the paginated list
- def per_page_option
- per_page = nil
- if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i)
- per_page = params[:per_page].to_s.to_i
- session[:per_page] = per_page
- elsif session[:per_page]
- per_page = session[:per_page]
- else
- per_page = Setting.per_page_options_array.first || 25
- end
- per_page
- end
-
- # qvalues http header parser
- # code taken from webrick
- def parse_qvalues(value)
- tmp = []
- if value
- parts = value.split(/,\s*/)
- parts.each {|part|
- if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
- val = m[1]
- q = (m[2] or 1).to_f
- tmp.push([val, q])
- end
- }
- tmp = tmp.sort_by{|val, q| -q}
- tmp.collect!{|val, q| val}
- end
- return tmp
- rescue
- nil
- end
-
- # Returns a string that can be used as filename value in Content-Disposition header
- def filename_for_content_disposition(name)
- request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
- end
-end
--- /dev/null
+# redMine - project management software
+# Copyright (C) 2006-2007 Jean-Philippe Lang
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+require 'uri'
+require 'cgi'
+
+class ApplicationController < ActionController::Base
+ include Redmine::I18n
+
+ layout 'base'
+
+ before_filter :user_setup, :check_if_login_required, :set_localization
+ filter_parameter_logging :password
+
+ include Redmine::MenuManager::MenuController
+ helper Redmine::MenuManager::MenuHelper
+
+ REDMINE_SUPPORTED_SCM.each do |scm|
+ require_dependency "repository/#{scm.underscore}"
+ end
+
+ def user_setup
+ # Check the settings cache for each request
+ Setting.check_cache
+ # Find the current user
+ User.current = find_current_user
+ end
+
+ # Returns the current user or nil if no user is logged in
+ # and starts a session if needed
+ def find_current_user
+ if session[:user_id]
+ # existing session
+ (User.active.find(session[:user_id]) rescue nil)
+ elsif cookies[:autologin] && Setting.autologin?
+ # auto-login feature starts a new session
+ user = User.try_to_autologin(cookies[:autologin])
+ session[:user_id] = user.id if user
+ user
+ elsif params[:format] == 'atom' && params[:key] && accept_key_auth_actions.include?(params[:action])
+ # RSS key authentication does not start a session
+ User.find_by_rss_key(params[:key])
+ end
+ end
+
+ # Sets the logged in user
+ def logged_user=(user)
+ if user && user.is_a?(User)
+ User.current = user
+ session[:user_id] = user.id
+ else
+ User.current = User.anonymous
+ session[:user_id] = nil
+ end
+ end
+
+ # check if login is globally required to access the application
+ def check_if_login_required
+ # no check needed if user is already logged in
+ return true if User.current.logged?
+ require_login if Setting.login_required?
+ end
+
+ def set_localization
+ lang = nil
+ if User.current.logged?
+ lang = find_language(User.current.language)
+ end
+ if lang.nil? && request.env['HTTP_ACCEPT_LANGUAGE']
+ accept_lang = parse_qvalues(request.env['HTTP_ACCEPT_LANGUAGE']).first.downcase
+ if !accept_lang.blank?
+ lang = find_language(accept_lang) || find_language(accept_lang.split('-').first)
+ end
+ end
+ lang ||= Setting.default_language
+ set_language_if_valid(lang)
+ end
+
+ def require_login
+ if !User.current.logged?
+ redirect_to :controller => "account", :action => "login", :back_url => url_for(params)
+ return false
+ end
+ true
+ end
+
+ def require_admin
+ return unless require_login
+ if !User.current.admin?
+ render_403
+ return false
+ end
+ true
+ end
+
+ def deny_access
+ User.current.logged? ? render_403 : require_login
+ end
+
+ # Authorize the user for the requested action
+ def authorize(ctrl = params[:controller], action = params[:action], global = false)
+ allowed = User.current.allowed_to?({:controller => ctrl, :action => action}, @project, :global => global)
+ allowed ? true : deny_access
+ end
+
+ # Authorize the user for the requested action outside a project
+ def authorize_global(ctrl = params[:controller], action = params[:action], global = true)
+ authorize(ctrl, action, global)
+ end
+
+ # make sure that the user is a member of the project (or admin) if project is private
+ # used as a before_filter for actions that do not require any particular permission on the project
+ def check_project_privacy
+ if @project && @project.active?
+ if @project.is_public? || User.current.member_of?(@project) || User.current.admin?
+ true
+ else
+ User.current.logged? ? render_403 : require_login
+ end
+ else
+ @project = nil
+ render_404
+ false
+ end
+ end
+
+ def redirect_back_or_default(default)
+ back_url = CGI.unescape(params[:back_url].to_s)
+ if !back_url.blank?
+ begin
+ uri = URI.parse(back_url)
+ # do not redirect user to another host or to the login or register page
+ if (uri.relative? || (uri.host == request.host)) && !uri.path.match(%r{/(login|account/register)})
+ redirect_to(back_url) and return
+ end
+ rescue URI::InvalidURIError
+ # redirect to default
+ end
+ end
+ redirect_to default
+ end
+
+ def render_403
+ @project = nil
+ render :template => "common/403", :layout => !request.xhr?, :status => 403
+ return false
+ end
+
+ def render_404
+ render :template => "common/404", :layout => !request.xhr?, :status => 404
+ return false
+ end
+
+ def render_error(msg)
+ flash.now[:error] = msg
+ render :text => '', :layout => !request.xhr?, :status => 500
+ end
+
+ def render_feed(items, options={})
+ @items = items || []
+ @items.sort! {|x,y| y.event_datetime <=> x.event_datetime }
+ @items = @items.slice(0, Setting.feeds_limit.to_i)
+ @title = options[:title] || Setting.app_title
+ render :template => "common/feed.atom.rxml", :layout => false, :content_type => 'application/atom+xml'
+ end
+
+ def self.accept_key_auth(*actions)
+ actions = actions.flatten.map(&:to_s)
+ write_inheritable_attribute('accept_key_auth_actions', actions)
+ end
+
+ def accept_key_auth_actions
+ self.class.read_inheritable_attribute('accept_key_auth_actions') || []
+ end
+
+ # TODO: move to model
+ def attach_files(obj, attachments)
+ attached = []
+ unsaved = []
+ if attachments && attachments.is_a?(Hash)
+ attachments.each_value do |attachment|
+ file = attachment['file']
+ next unless file && file.size > 0
+ a = Attachment.create(:container => obj,
+ :file => file,
+ :description => attachment['description'].to_s.strip,
+ :author => User.current)
+ a.new_record? ? (unsaved << a) : (attached << a)
+ end
+ if unsaved.any?
+ flash[:warning] = l(:warning_attachments_not_saved, unsaved.size)
+ end
+ end
+ attached
+ end
+
+ # Returns the number of objects that should be displayed
+ # on the paginated list
+ def per_page_option
+ per_page = nil
+ if params[:per_page] && Setting.per_page_options_array.include?(params[:per_page].to_s.to_i)
+ per_page = params[:per_page].to_s.to_i
+ session[:per_page] = per_page
+ elsif session[:per_page]
+ per_page = session[:per_page]
+ else
+ per_page = Setting.per_page_options_array.first || 25
+ end
+ per_page
+ end
+
+ # qvalues http header parser
+ # code taken from webrick
+ def parse_qvalues(value)
+ tmp = []
+ if value
+ parts = value.split(/,\s*/)
+ parts.each {|part|
+ if m = %r{^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$}.match(part)
+ val = m[1]
+ q = (m[2] or 1).to_f
+ tmp.push([val, q])
+ end
+ }
+ tmp = tmp.sort_by{|val, q| -q}
+ tmp.collect!{|val, q| val}
+ end
+ return tmp
+ rescue
+ nil
+ end
+
+ # Returns a string that can be used as filename value in Content-Disposition header
+ def filename_for_content_disposition(name)
+ request.env['HTTP_USER_AGENT'] =~ %r{MSIE} ? ERB::Util.url_encode(name) : name
+ end
+end
def graph_commits_per_author(repository)
commits_by_author = repository.changesets.count(:all, :group => :committer)
- commits_by_author.sort! {|x, y| x.last <=> y.last}
+ commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}
changes_by_author = repository.changes.count(:all, :group => :committer)
h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
class Mailer < ActionMailer::Base
+ layout 'mailer'
helper :application
helper :issues
helper :custom_fields
subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
body :issue => issue,
:issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
+ render_multipart('issue_add', body)
end
# Builds a tmail object used to email recipients of the edited issue.
body :issue => issue,
:journal => journal,
:issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
+
+ render_multipart('issue_edit', body)
end
def reminder(user, issues, days)
body :issues => issues,
:days => days,
:issues_url => url_for(:controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => user.id, :sort_key => 'due_date', :sort_order => 'asc')
+ render_multipart('reminder', body)
end
# Builds a tmail object used to email users belonging to the added document's project.
subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
body :document => document,
:document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
+ render_multipart('document_added', body)
end
# Builds a tmail object used to email recipients of a project when an attachements are added.
body :attachments => attachments,
:added_to => added_to,
:added_to_url => added_to_url
+ render_multipart('attachments_added', body)
end
# Builds a tmail object used to email recipients of a news' project when a news item is added.
subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
body :news => news,
:news_url => url_for(:controller => 'news', :action => 'show', :id => news)
+ render_multipart('news_added', body)
end
# Builds a tmail object used to email the specified recipients of the specified message that was posted.
subject "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
body :message => message,
:message_url => url_for(:controller => 'messages', :action => 'show', :board_id => message.board_id, :id => message.root)
+ render_multipart('message_posted', body)
end
# Builds a tmail object used to email the recipients of a project of the specified wiki content was added.
subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :page => wiki_content.page.pretty_title)}"
body :wiki_content => wiki_content,
:wiki_content_url => url_for(:controller => 'wiki', :action => 'index', :id => wiki_content.project, :page => wiki_content.page.title)
+ render_multipart('wiki_content_added', body)
end
# Builds a tmail object used to email the recipients of a project of the specified wiki content was updated.
body :wiki_content => wiki_content,
:wiki_content_url => url_for(:controller => 'wiki', :action => 'index', :id => wiki_content.project, :page => wiki_content.page.title),
:wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff', :id => wiki_content.project, :page => wiki_content.page.title, :version => wiki_content.version)
+ render_multipart('wiki_content_updated', body)
end
# Builds a tmail object used to email the specified user their account information.
body :user => user,
:password => password,
:login_url => url_for(:controller => 'account', :action => 'login')
+ render_multipart('account_information', body)
end
# Builds a tmail object used to email all active administrators of an account activation request.
subject l(:mail_subject_account_activation_request, Setting.app_title)
body :user => user,
:url => url_for(:controller => 'users', :action => 'index', :status => User::STATUS_REGISTERED, :sort_key => 'created_on', :sort_order => 'desc')
+ render_multipart('account_activation_request', body)
end
# Builds a tmail object used to email the specified user that their account was activated by an administrator.
subject l(:mail_subject_register, Setting.app_title)
body :user => user,
:login_url => url_for(:controller => 'account', :action => 'login')
+ render_multipart('account_activated', body)
end
def lost_password(token)
subject l(:mail_subject_lost_password, Setting.app_title)
body :token => token,
:url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
+ render_multipart('lost_password', body)
end
def register(token)
subject l(:mail_subject_register, Setting.app_title)
body :token => token,
:url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
+ render_multipart('register', body)
end
def test(user)
recipients user.mail
subject 'Redmine test'
body :url => url_for(:controller => 'welcome')
+ render_multipart('test', body)
end
# Overrides default deliver! method to prevent from sending an email
super
end
- # Renders a message with the corresponding layout
- def render_message(method_name, body)
- layout = method_name.to_s.match(%r{text\.html\.(rhtml|rxml)}) ? 'layout.text.html.rhtml' : 'layout.text.plain.rhtml'
- body[:content_for_layout] = render(:file => method_name, :body => body)
- ActionView::Base.new(template_root, body, self).render(:file => "mailer/#{layout}", :use_full_path => true)
- end
-
- # for the case of plain text only
- def body(*params)
- value = super(*params)
- if Setting.plain_text_mail?
- templates = Dir.glob("#{template_path}/#{@template}.text.plain.{rhtml,erb}")
- unless String === @body or templates.empty?
- template = File.basename(templates.first)
- @body[:content_for_layout] = render(:file => template, :body => @body)
- @body = ActionView::Base.new(template_root, @body, self).render(:file => "mailer/layout.text.plain.rhtml", :use_full_path => true)
- return @body
- end
- end
- return value
+ # Rails 2.3 has problems rendering implicit multipart messages with
+ # layouts so this method will wrap an multipart messages with
+ # explicit parts.
+ #
+ # https://rails.lighthouseapp.com/projects/8994/tickets/2338-actionmailer-mailer-views-and-content-type
+ # https://rails.lighthouseapp.com/projects/8994/tickets/1799-actionmailer-doesnt-set-template_format-when-rendering-layouts
+
+ def render_multipart(method_name, body)
+ content_type "multipart/alternative"
+ part :content_type => "text/plain", :body => render(:file => "#{method_name}.text.plain.rhtml", :body => body, :layout => 'mailer.text.plain.erb')
+ part :content_type => "text/html", :body => render_message("#{method_name}.text.html.rhtml", body) unless Setting.plain_text_mail?
end
# Makes partial rendering work with Rails 1.2 (retro-compatibility)
--- /dev/null
+<html>
+<head>
+<style>
+body {
+ font-family: Verdana, sans-serif;
+ font-size: 0.8em;
+ color:#484848;
+}
+h1, h2, h3 { font-family: "Trebuchet MS", Verdana, sans-serif; margin: 0px; }
+h1 { font-size: 1.2em; }
+h2, h3 { font-size: 1.1em; }
+a, a:link, a:visited { color: #2A5685;}
+a:hover, a:active { color: #c61a1a; }
+a.wiki-anchor { display: none; }
+hr {
+ width: 100%;
+ height: 1px;
+ background: #ccc;
+ border: 0;
+}
+.footer {
+ font-size: 0.8em;
+ font-style: italic;
+}
+</style>
+</head>
+<body>
+<%= yield %>
+<hr />
+<span class="footer"><%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_footer) %></span>
+</body>
+</html>
--- /dev/null
+<%= yield %>
+--
+<%= Setting.emails_footer %>
+++ /dev/null
-<html>
-<head>
-<style>
-body {
- font-family: Verdana, sans-serif;
- font-size: 0.8em;
- color:#484848;
-}
-h1, h2, h3 { font-family: "Trebuchet MS", Verdana, sans-serif; margin: 0px; }
-h1 { font-size: 1.2em; }
-h2, h3 { font-size: 1.1em; }
-a, a:link, a:visited { color: #2A5685;}
-a:hover, a:active { color: #c61a1a; }
-a.wiki-anchor { display: none; }
-hr {
- width: 100%;
- height: 1px;
- background: #ccc;
- border: 0;
-}
-.footer {
- font-size: 0.8em;
- font-style: italic;
-}
-</style>
-</head>
-<body>
-<%= yield %>
-<hr />
-<span class="footer"><%= Redmine::WikiFormatting.to_html(Setting.text_formatting, Setting.emails_footer) %></span>
-</body>
-</html>
+++ /dev/null
-<%= yield %>
---
-<%= Setting.emails_footer %>
<div class="box tabular settings">
<p><label><%= l(:setting_login_required) %></label>
-<%= check_box_tag 'settings[login_required]', 1, Setting.login_required? %><%= hidden_field_tag 'settings[login_required]', 0 %></p>
+<%= hidden_field_tag 'settings[login_required]', 0 %>
+<%= check_box_tag 'settings[login_required]', 1, Setting.login_required? %>
+</p>
<p><label><%= l(:setting_autologin) %></label>
<%= select_tag 'settings[autologin]', options_for_select( [[l(:label_disabled), "0"]] + [1, 7, 30, 365].collect{|days| [l('datetime.distance_in_words.x_days', :count => days), days.to_s]}, Setting.autologin) %></p>
<%= text_field_tag 'settings[password_min_length]', Setting.password_min_length, :size => 6 %></p>
<p><label><%= l(:label_password_lost) %></label>
-<%= check_box_tag 'settings[lost_password]', 1, Setting.lost_password? %><%= hidden_field_tag 'settings[lost_password]', 0 %></p>
+<%= hidden_field_tag 'settings[lost_password]', 0 %>
+<%= check_box_tag 'settings[lost_password]', 1, Setting.lost_password? %>
+</p>
<p><label><%= l(:setting_openid) %></label>
-<%= check_box_tag 'settings[openid]', 1, Setting.openid?, :disabled => !Object.const_defined?(:OpenID) %><%= hidden_field_tag 'settings[openid]', 0 %></p>
+<%= hidden_field_tag 'settings[openid]', 0 %>
+<%= check_box_tag 'settings[openid]', 1, Setting.openid?, :disabled => !Object.const_defined?(:OpenID) %>
+</p>
</div>
<div style="float:right;">
<%= select_tag 'settings[user_format]', options_for_select( @options[:user_format], Setting.user_format.to_s ) %></p>
<p><label><%= l(:setting_gravatar_enabled) %></label>
-<%= check_box_tag 'settings[gravatar_enabled]', 1, Setting.gravatar_enabled? %><%= hidden_field_tag 'settings[gravatar_enabled]', 0 %></p>
+<%= hidden_field_tag 'settings[gravatar_enabled]', 0 %>
+<%= check_box_tag 'settings[gravatar_enabled]', 1, Setting.gravatar_enabled? %>
+</p>
</div>
<%= submit_tag l(:button_save) %>
<div class="box tabular settings">
<p><label><%= l(:setting_cross_project_issue_relations) %></label>
-<%= check_box_tag 'settings[cross_project_issue_relations]', 1, Setting.cross_project_issue_relations? %><%= hidden_field_tag 'settings[cross_project_issue_relations]', 0 %></p>
+<%= hidden_field_tag 'settings[cross_project_issue_relations]', 0 %>
+<%= check_box_tag 'settings[cross_project_issue_relations]', 1, Setting.cross_project_issue_relations? %>
+</p>
<p><label><%= l(:setting_display_subprojects_issues) %></label>
-<%= check_box_tag 'settings[display_subprojects_issues]', 1, Setting.display_subprojects_issues? %><%= hidden_field_tag 'settings[display_subprojects_issues]', 0 %></p>
+<%= hidden_field_tag 'settings[display_subprojects_issues]', 0 %>
+<%= check_box_tag 'settings[display_subprojects_issues]', 1, Setting.display_subprojects_issues? %>
+</p>
<p><label><%= l(:setting_issues_export_limit) %></label>
<%= text_field_tag 'settings[issues_export_limit]', Setting.issues_export_limit, :size => 6 %></p>
<div class="box tabular settings">
<p><label><%= l(:setting_mail_handler_api_enabled) %></label>
+<%= hidden_field_tag 'settings[mail_handler_api_enabled]', 0 %>
<%= check_box_tag 'settings[mail_handler_api_enabled]', 1, Setting.mail_handler_api_enabled?,
:onclick => "if (this.checked) { Form.Element.enable('settings_mail_handler_api_key'); } else { Form.Element.disable('settings_mail_handler_api_key'); }" %>
-<%= hidden_field_tag 'settings[mail_handler_api_enabled]', 0 %></p>
+</p>
<p><label><%= l(:setting_mail_handler_api_key) %></label>
<%= text_field_tag 'settings[mail_handler_api_key]', Setting.mail_handler_api_key,
<%= text_field_tag 'settings[mail_from]', Setting.mail_from, :size => 60 %></p>
<p><label><%= l(:setting_bcc_recipients) %></label>
+<%= hidden_field_tag 'settings[bcc_recipients]', 0 %>
<%= check_box_tag 'settings[bcc_recipients]', 1, Setting.bcc_recipients? %>
-<%= hidden_field_tag 'settings[bcc_recipients]', 0 %></p>
+</p>
<p><label><%= l(:setting_plain_text_mail) %></label>
+<%= hidden_field_tag 'settings[plain_text_mail]', 0 %>
<%= check_box_tag 'settings[plain_text_mail]', 1, Setting.plain_text_mail? %>
-<%= hidden_field_tag 'settings[plain_text_mail]', 0 %></p>
+</p>
</div>
<fieldset class="box" id="notified_events"><legend><%=l(:text_select_mail_notifications)%></legend>
<div class="box tabular settings">
<p><label><%= l(:setting_default_projects_public) %></label>
-<%= check_box_tag 'settings[default_projects_public]', 1, Setting.default_projects_public? %><%= hidden_field_tag 'settings[default_projects_public]', 0 %></p>
+<%= hidden_field_tag 'settings[default_projects_public]', 0 %>
+<%= check_box_tag 'settings[default_projects_public]', 1, Setting.default_projects_public? %>
+</p>
<p><label><%= l(:setting_sequential_project_identifiers) %></label>
-<%= check_box_tag 'settings[sequential_project_identifiers]', 1, Setting.sequential_project_identifiers? %><%= hidden_field_tag 'settings[sequential_project_identifiers]', 0 %></p>
+<%= hidden_field_tag 'settings[sequential_project_identifiers]', 0 %>
+<%= check_box_tag 'settings[sequential_project_identifiers]', 1, Setting.sequential_project_identifiers? %>
+</p>
<p><label><%= l(:setting_new_project_user_role_id) %></label>
<%= select_tag('settings[new_project_user_role_id]', options_for_select([["--- #{l(:actionview_instancetag_blank_option)} ---", '']] + Role.find_all_givable.collect {|r| [r.name, r.id]}, Setting.new_project_user_role_id.to_i)) %></p>
<div class="box tabular settings">
<p><label><%= l(:setting_autofetch_changesets) %></label>
-<%= check_box_tag 'settings[autofetch_changesets]', 1, Setting.autofetch_changesets? %><%= hidden_field_tag 'settings[autofetch_changesets]', 0 %></p>
+<%= hidden_field_tag 'settings[autofetch_changesets]', 0 %>
+<%= check_box_tag 'settings[autofetch_changesets]', 1, Setting.autofetch_changesets? %>
+</p>
<p><label><%= l(:setting_sys_api_enabled) %></label>
-<%= check_box_tag 'settings[sys_api_enabled]', 1, Setting.sys_api_enabled? %><%= hidden_field_tag 'settings[sys_api_enabled]', 0 %></p>
+<%= hidden_field_tag 'settings[sys_api_enabled]', 0 %>
+<%= check_box_tag 'settings[sys_api_enabled]', 1, Setting.sys_api_enabled? %>
+</p>
<p><label><%= l(:setting_enabled_scm) %></label>
<% REDMINE_SUPPORTED_SCM.each do |scm| -%>
# Don't change this file!
# Configure your app in config/environment.rb and config/environments/*.rb
-RAILS_ROOT = File.expand_path("#{File.dirname(__FILE__)}/..") unless defined?(RAILS_ROOT)
+RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
module Rails
class << self
def load_initializer
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
Rails::Initializer.run(:install_gem_spec_stubs)
+ Rails::GemDependency.add_frozen_gem_path
end
end
end
def load_rubygems
+ min_version = '1.3.2'
require 'rubygems'
- min_version = '1.3.1'
unless rubygems_version >= min_version
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
exit 1
# ENV['RAILS_ENV'] ||= 'production'
# Specifies gem version of Rails to use when vendor/rails is not present
-RAILS_GEM_VERSION = '2.2.2' unless defined? RAILS_GEM_VERSION
+RAILS_GEM_VERSION = '2.3.4' unless defined? RAILS_GEM_VERSION
# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')
end
else
attr_name = @base.class.human_attribute_name(attr)
- full_messages << attr_name + ' ' + message
+ full_messages << attr_name + ' ' + message.to_s
end
end
end
--- /dev/null
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying do debug a problem that might steem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
\ No newline at end of file
--- /dev/null
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format
+# (all these examples are active by default):
+# ActiveSupport::Inflector.inflections do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
over_x_years:
one: "over 1 year"
other: "over {{count}} years"
+
+ number:
+ human:
+ format:
+ precision: 1
+ delimiter: ""
+ storage_units:
+ format: "%n %u"
+ units:
+ kb: KB
+ tb: TB
+ gb: GB
+ byte:
+ one: Byte
+ other: Bytes
+ mb: 'MB'
# Used in array.to_sentence.
support:
format:
delimiter: ""
precision: 1
-
-
-
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
# Used in array.to_sentence.
support:
over_x_years:
one: "més d'un any"
other: "més de {{count}} anys"
+
+ number:
+ human:
+ format:
+ delimiter: ""
+ precision: 1
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
# Used in array.to_sentence.
support:
over_x_years:
one: "více než 1 rok"
other: "více než {{count}} roky"
+
+ number:
+ human:
+ format:
+ precision: 1
+ delimiter: ""
+ storage_units:
+ format: "%n %u"
+ units:
+ kb: KB
+ tb: TB
+ gb: GB
+ byte:
+ one: Byte
+ other: Bytes
+ mb: MB
# Used in array.to_sentence.
support:
# separator:
delimiter: ""
precision: 1
- storage_units: [Bytes, KB, MB, GB, TB]
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
percentage:
format:
# separator:
format:
delimiter: ""
precision: 1
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
support:
array:
one: "πάνω από 1 χρόνο"
other: "πάνω από {{count}} χρόνια"
+ number:
+ human:
+ format:
+ precision: 1
+ delimiter: ""
+ storage_units:
+ format: "%n %u"
+ units:
+ kb: KB
+ tb: TB
+ gb: GB
+ byte:
+ one: Byte
+ other: Bytes
+ mb: MB
+
# Used in array.to_sentence.
support:
array:
over_x_years:
one: "over 1 year"
other: "over {{count}} years"
+
+ number:
+ human:
+ format:
+ delimiter: ""
+ precision: 1
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
+
# Used in array.to_sentence.
support:
# separator:
delimiter: ""
precision: 1
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
# Used in distance_of_time_in_words(), distance_of_time_in_words_to_now(), time_ago_in_words()
datetime:
format:
delimiter: ""
precision: 1
- storage_units: [Tavua, KB, MB, GB, TB]
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Tavua"
+ other: "Tavua"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
datetime:
distance_in_words:
human:
format:
precision: 2
- storage_units: [ Octet, ko, Mo, Go, To ]
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Octet"
+ other: "Octet"
+ kb: "ko"
+ mb: "Mo"
+ gb: "Go"
+ tb: "To"
support:
array:
# separator:
delimiter: ""
precision: 1
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
date:
unit: 'שח'
precision: 2
format: '%u %n'
+ human:
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
support:
array:
format:
delimiter: ""
precision: 1
- storage_units: [bájt, KB, MB, GB, TB]
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "bájt"
+ other: "bájt"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
support:
array:
unit: '€'
precision: 2
format: '%n %u'
+ human:
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
support:
array:
format:
delimiter: ""
precision: 1
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
activerecord:
errors:
# separator:
delimiter: ""
precision: 1
- storage_units: [Bytes, KB, MB, GB, TB]
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
# Used in array.to_sentence.
support:
format:
delimiter: ""
precision: 1
- storage_units: [baitai, KB, MB, GB, TB]
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "baitai"
+ other: "baitai"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
datetime:
distance_in_words:
over_x_years:
one: "over 1 jaar"
other: "over {{count}} jaren"
+
+ number:
+ human:
+ format:
+ precision: 1
+ delimiter: ""
+ storage_units:
+ format: "%n %u"
+ units:
+ kb: KB
+ tb: TB
+ gb: GB
+ byte:
+ one: Byte
+ other: Bytes
+ mb: MB
# Used in array.to_sentence.
support:
format:
delimiter: ""
precision: 4
+ human:
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
+
activerecord:
errors:
template:
format:
delimiter: ""
precision: 1
- storage_units: [B, KB, MB, GB, TB]
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "B"
+ other: "B"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
date:
formats:
format:
precision: 1
delimiter: '.'
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
support:
array:
sentence_connector: "e"
format:
precision: 1
delimiter: ''
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
activerecord:
errors:
over_x_years:
one: "peste un an"
other: "peste {{count}} ani"
+
+ number:
+ human:
+ format:
+ precision: 1
+ delimiter: ""
+ storage_units:
+ format: "%n %u"
+ units:
+ kb: KB
+ tb: TB
+ gb: GB
+ byte:
+ one: Byte
+ other: Bytes
+ mb: MB
# Used in array.to_sentence.
support:
over_x_years:
one: "cez 1 rok"
other: "cez {{count}} roky/ov"
+
+ number:
+ human:
+ format:
+ precision: 1
+ delimiter: ""
+ storage_units:
+ format: "%n %u"
+ units:
+ kb: KB
+ tb: TB
+ gb: GB
+ byte:
+ one: Byte
+ other: Bytes
+ mb: MB
# Used in array.to_sentence.
support:
over_x_years:
one: "over 1 year"
other: "over {{count}} years"
+
+ number:
+ human:
+ format:
+ precision: 1
+ delimiter: ""
+ storage_units:
+ format: "%n %u"
+ units:
+ kb: KB
+ tb: TB
+ gb: GB
+ byte:
+ one: Byte
+ other: Bytes
+ mb: MB
# Used in array.to_sentence.
support:
unit: 'ДИН'
precision: 2
format: '%n %u'
+ human:
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
support:
array:
# separator:
delimiter: ""
# precision: 1
- storage_units: [Byte, KB, MB, GB, TB]
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
# Used in distance_of_time_in_words(), distance_of_time_in_words_to_now(), time_ago_in_words()
datetime:
over_x_years:
one: "over 1 year"
other: "over {{count}} years"
+
+ number:
+ human:
+ format:
+ precision: 1
+ delimiter: ""
+ storage_units:
+ format: "%n %u"
+ units:
+ kb: KB
+ tb: TB
+ gb: GB
+ byte:
+ one: Byte
+ other: Bytes
+ mb: MB
# Used in array.to_sentence.
support:
delimiter: '.'
separator: ','
precision: 2
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
support:
array:
over_x_years:
one: "over 1 year"
other: "over {{count}} years"
+
+ number:
+ human:
+ format:
+ precision: 1
+ delimiter: ""
+ storage_units:
+ format: "%n %u"
+ units:
+ kb: KB
+ tb: TB
+ gb: GB
+ byte:
+ one: Byte
+ other: Bytes
+ mb: MB
# Used in array.to_sentence.
support:
# separator:
delimiter: ""
precision: 1
- storage_units: [Bytes, KB, MB, GB, TB]
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
# Used in distance_of_time_in_words(), distance_of_time_in_words_to_now(), time_ago_in_words()
datetime:
precision: 1
# 儲存單位輸出格式.
# %u 是儲存單位, %n 是數值 (預設值: 2 MB)
+ storage_units:
format: "%n %u"
- storage_units:
+ units:
byte:
one: "位元組 (B)"
other: "位元組 (B)"
format:
delimiter: ""
precision: 1
- storage_units: [Bytes, KB, MB, GB, TB]
+ storage_units:
+ format: "%n %u"
+ units:
+ byte:
+ one: "Byte"
+ other: "Bytes"
+ kb: "KB"
+ mb: "MB"
+ gb: "GB"
+ tb: "TB"
support:
array:
# map.connect 'products/:id', :controller => 'catalog', :action => 'view'
# Keep in mind you can assign values other than :controller and :action
- # Allow Redmine plugins to map routes and potentially override them
- Rails.plugins.each do |plugin|
- map.from_plugin plugin.name.to_sym
- end
-
map.home '', :controller => 'welcome'
map.signin 'login', :controller => 'account', :action => 'login'
return '' if options.delete(:no_label)
text = options[:label].is_a?(Symbol) ? l(options[:label]) : options[:label]
text ||= l(("field_" + field.to_s.gsub(/\_id$/, "")).to_sym)
- text << @template.content_tag("span", " *", :class => "required") if options.delete(:required)
+ text += @template.content_tag("span", " *", :class => "required") if options.delete(:required)
@template.content_tag("label", text,
:class => (@object && @object.errors[field] ? "error" : nil),
:for => (@object_name.to_s + "_" + field.to_s))
# Re-raise errors caught by the controller.
class AccountController; def rescue_action(e) raise e end; end
-class AccountControllerTest < Test::Unit::TestCase
+class AccountControllerTest < ActionController::TestCase
fixtures :users, :roles
def setup
# Re-raise errors caught by the controller.
class AdminController; def rescue_action(e) raise e end; end
-class AdminControllerTest < Test::Unit::TestCase
+class AdminControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles
def setup
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
require File.dirname(__FILE__) + '/../test_helper'
-require 'application'
+require 'application_controller'
# Re-raise errors caught by the controller.
class ApplicationController; def rescue_action(e) raise e end; end
-class ApplicationControllerTest < Test::Unit::TestCase
+class ApplicationControllerTest < ActionController::TestCase
include Redmine::I18n
def setup
class AttachmentsController; def rescue_action(e) raise e end; end
-class AttachmentsControllerTest < Test::Unit::TestCase
+class AttachmentsControllerTest < ActionController::TestCase
fixtures :users, :projects, :roles, :members, :member_roles, :enabled_modules, :issues, :trackers, :attachments,
:versions, :wiki_pages, :wikis, :documents
# Re-raise errors caught by the controller.
class BoardsController; def rescue_action(e) raise e end; end
-class BoardsControllerTest < Test::Unit::TestCase
+class BoardsControllerTest < ActionController::TestCase
fixtures :projects, :users, :members, :member_roles, :roles, :boards, :messages, :enabled_modules
def setup
# Re-raise errors caught by the controller.\r
class CustomFieldsController; def rescue_action(e) raise e end; end\r
\r
-class CustomFieldsControllerTest < Test::Unit::TestCase\r
+class CustomFieldsControllerTest < ActionController::TestCase\r
fixtures :custom_fields, :trackers, :users\r
\r
def setup\r
# Re-raise errors caught by the controller.
class DocumentsController; def rescue_action(e) raise e end; end
-class DocumentsControllerTest < Test::Unit::TestCase
+class DocumentsControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :documents, :enumerations
def setup
# Re-raise errors caught by the controller.
class EnumerationsController; def rescue_action(e) raise e end; end
-class EnumerationsControllerTest < Test::Unit::TestCase
+class EnumerationsControllerTest < ActionController::TestCase
fixtures :enumerations, :issues, :users
def setup
# Re-raise errors caught by the controller.
class GroupsController; def rescue_action(e) raise e end; end
-class GroupsControllerTest < Test::Unit::TestCase
+class GroupsControllerTest < ActionController::TestCase
fixtures :projects, :users, :members, :member_roles
def setup
# Re-raise errors caught by the controller.
class IssueCategoriesController; def rescue_action(e) raise e end; end
-class IssueCategoriesControllerTest < Test::Unit::TestCase
+class IssueCategoriesControllerTest < ActionController::TestCase
fixtures :projects, :users, :members, :member_roles, :roles, :enabled_modules, :issue_categories
def setup
class IssueRelationsController; def rescue_action(e) raise e end; end
-class IssueRelationsControllerTest < Test::Unit::TestCase
+class IssueRelationsControllerTest < ActionController::TestCase
fixtures :projects,
:users,
:roles,
# Re-raise errors caught by the controller.
class IssuesController; def rescue_action(e) raise e end; end
-class IssuesControllerTest < Test::Unit::TestCase
+class IssuesControllerTest < ActionController::TestCase
fixtures :projects,
:users,
:roles,
:custom_fields_trackers,
:time_entries,
:journals,
- :journal_details
+ :journal_details,
+ :queries
def setup
@controller = IssuesController.new
def test_post_new
@request.session[:user_id] = 2
- post :new, :project_id => 1,
- :issue => {:tracker_id => 3,
- :subject => 'This is the test_new issue',
- :description => 'This is the description',
- :priority_id => 5,
- :estimated_hours => '',
- :custom_field_values => {'2' => 'Value for field 2'}}
- assert_redirected_to :action => 'show'
+ assert_difference 'Issue.count' do
+ post :new, :project_id => 1,
+ :issue => {:tracker_id => 3,
+ :subject => 'This is the test_new issue',
+ :description => 'This is the description',
+ :priority_id => 5,
+ :estimated_hours => '',
+ :custom_field_values => {'2' => 'Value for field 2'}}
+ end
+ assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
issue = Issue.find_by_subject('This is the test_new issue')
assert_not_nil issue
def test_post_new_without_custom_fields_param
@request.session[:user_id] = 2
- post :new, :project_id => 1,
- :issue => {:tracker_id => 1,
- :subject => 'This is the test_new issue',
- :description => 'This is the description',
- :priority_id => 5}
- assert_redirected_to :action => 'show'
+ assert_difference 'Issue.count' do
+ post :new, :project_id => 1,
+ :issue => {:tracker_id => 1,
+ :subject => 'This is the test_new issue',
+ :description => 'This is the description',
+ :priority_id => 5}
+ end
+ assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
end
def test_post_new_with_required_custom_field_and_without_custom_fields_param
def test_post_new_should_send_a_notification
ActionMailer::Base.deliveries.clear
@request.session[:user_id] = 2
- post :new, :project_id => 1,
- :issue => {:tracker_id => 3,
- :subject => 'This is the test_new issue',
- :description => 'This is the description',
- :priority_id => 5,
- :estimated_hours => '',
- :custom_field_values => {'2' => 'Value for field 2'}}
- assert_redirected_to :action => 'show'
+ assert_difference 'Issue.count' do
+ post :new, :project_id => 1,
+ :issue => {:tracker_id => 3,
+ :subject => 'This is the test_new issue',
+ :description => 'This is the description',
+ :priority_id => 5,
+ :estimated_hours => '',
+ :custom_field_values => {'2' => 'Value for field 2'}}
+ end
+ assert_redirected_to :controller => 'issues', :action => 'show', :id => Issue.last.id
assert_equal 1, ActionMailer::Base.deliveries.size
end
# Re-raise errors caught by the controller.
class JournalsController; def rescue_action(e) raise e end; end
-class JournalsControllerTest < Test::Unit::TestCase
+class JournalsControllerTest < ActionController::TestCase
fixtures :projects, :users, :members, :member_roles, :roles, :issues, :journals, :journal_details, :enabled_modules
def setup
# Re-raise errors caught by the controller.
class MailHandlerController; def rescue_action(e) raise e end; end
-class MailHandlerControllerTest < Test::Unit::TestCase
+class MailHandlerControllerTest < ActionController::TestCase
fixtures :users, :projects, :enabled_modules, :roles, :members, :member_roles, :issues, :issue_statuses, :trackers, :enumerations
FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
class MembersController; def rescue_action(e) raise e end; end
-class MembersControllerTest < Test::Unit::TestCase
+class MembersControllerTest < ActionController::TestCase
fixtures :projects, :members, :member_roles, :roles, :users
def setup
# Re-raise errors caught by the controller.
class MessagesController; def rescue_action(e) raise e end; end
-class MessagesControllerTest < Test::Unit::TestCase
+class MessagesControllerTest < ActionController::TestCase
fixtures :projects, :users, :members, :member_roles, :roles, :boards, :messages, :enabled_modules
def setup
# Re-raise errors caught by the controller.
class MyController; def rescue_action(e) raise e end; end
-class MyControllerTest < Test::Unit::TestCase
+class MyControllerTest < ActionController::TestCase
fixtures :users, :issues, :issue_statuses, :trackers, :enumerations, :custom_fields
def setup
# Re-raise errors caught by the controller.
class NewsController; def rescue_action(e) raise e end; end
-class NewsControllerTest < Test::Unit::TestCase
+class NewsControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :news, :comments
def setup
# Re-raise errors caught by the controller.
class ProjectsController; def rescue_action(e) raise e end; end
-class ProjectsControllerTest < Test::Unit::TestCase
+class ProjectsControllerTest < ActionController::TestCase
fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
:trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
:attachments
# Re-raise errors caught by the controller.
class QueriesController; def rescue_action(e) raise e end; end
-class QueriesControllerTest < Test::Unit::TestCase
+class QueriesControllerTest < ActionController::TestCase
fixtures :projects, :users, :members, :member_roles, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :custom_fields, :custom_values, :queries
def setup
:query => {"name" => "test_new_project_public_query", "is_public" => "1"}
q = Query.find_by_name('test_new_project_public_query')
- assert_redirected_to :controller => 'issues', :action => 'index', :query_id => q
+ assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q
assert q.is_public?
assert q.has_default_columns?
assert q.valid?
:query => {"name" => "test_new_project_private_query", "is_public" => "1"}
q = Query.find_by_name('test_new_project_private_query')
- assert_redirected_to :controller => 'issues', :action => 'index', :query_id => q
+ assert_redirected_to :controller => 'issues', :action => 'index', :project_id => 'ecookbook', :query_id => q
assert !q.is_public?
assert q.has_default_columns?
assert q.valid?
:query => {"name" => "test_new_global_private_query", "is_public" => "1", "column_names" => ["", "tracker", "subject", "priority", "category"]}
q = Query.find_by_name('test_new_global_private_query')
- assert_redirected_to :controller => 'issues', :action => 'index', :query_id => q
+ assert_redirected_to :controller => 'issues', :action => 'index', :project_id => nil, :query_id => q
assert !q.is_public?
assert !q.has_default_columns?
assert_equal [:tracker, :subject, :priority, :category], q.columns.collect {|c| c.name}
class ReportsController; def rescue_action(e) raise e end; end
-class ReportsControllerTest < Test::Unit::TestCase
+class ReportsControllerTest < ActionController::TestCase
fixtures :all
def setup
# Re-raise errors caught by the controller.
class RepositoriesController; def rescue_action(e) raise e end; end
-class RepositoriesBazaarControllerTest < Test::Unit::TestCase
+class RepositoriesBazaarControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules
# No '..' in the repository path
# Re-raise errors caught by the controller.
class RepositoriesController; def rescue_action(e) raise e end; end
-class RepositoriesControllerTest < Test::Unit::TestCase
+class RepositoriesControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :issues, :issue_statuses, :changesets, :changes, :issue_categories, :enumerations, :custom_fields, :custom_values, :trackers
def setup
# Re-raise errors caught by the controller.
class RepositoriesController; def rescue_action(e) raise e end; end
-class RepositoriesCvsControllerTest < Test::Unit::TestCase
+class RepositoriesCvsControllerTest < ActionController::TestCase
# No '..' in the repository path
REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/cvs_repository'
# Re-raise errors caught by the controller.
class RepositoriesController; def rescue_action(e) raise e end; end
-class RepositoriesDarcsControllerTest < Test::Unit::TestCase
+class RepositoriesDarcsControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules
# No '..' in the repository path
# Re-raise errors caught by the controller.
class RepositoriesController; def rescue_action(e) raise e end; end
-class RepositoriesGitControllerTest < Test::Unit::TestCase
+class RepositoriesGitControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules
# No '..' in the repository path
# Re-raise errors caught by the controller.
class RepositoriesController; def rescue_action(e) raise e end; end
-class RepositoriesMercurialControllerTest < Test::Unit::TestCase
+class RepositoriesMercurialControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :repositories, :enabled_modules
# No '..' in the repository path
# Re-raise errors caught by the controller.
class RepositoriesController; def rescue_action(e) raise e end; end
-class RepositoriesSubversionControllerTest < Test::Unit::TestCase
+class RepositoriesSubversionControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
:repositories, :issues, :issue_statuses, :changesets, :changes,
:issue_categories, :enumerations, :custom_fields, :custom_values, :trackers
# Re-raise errors caught by the controller.
class RolesController; def rescue_action(e) raise e end; end
-class RolesControllerTest < Test::Unit::TestCase
+class RolesControllerTest < ActionController::TestCase
fixtures :roles, :users, :members, :member_roles, :workflows
def setup
# Re-raise errors caught by the controller.
class SearchController; def rescue_action(e) raise e end; end
-class SearchControllerTest < Test::Unit::TestCase
+class SearchControllerTest < ActionController::TestCase
fixtures :projects, :enabled_modules, :roles, :users, :members, :member_roles,
:issues, :trackers, :issue_statuses,
:custom_fields, :custom_values,
# Re-raise errors caught by the controller.
class SettingsController; def rescue_action(e) raise e end; end
-class SettingsControllerTest < Test::Unit::TestCase
+class SettingsControllerTest < ActionController::TestCase
fixtures :users
def setup
# Re-raise errors caught by the controller.
class SysController; def rescue_action(e) raise e end; end
-class SysControllerTest < Test::Unit::TestCase
+class SysControllerTest < ActionController::TestCase
fixtures :projects, :repositories
def setup
# Re-raise errors caught by the controller.
class TimelogController; def rescue_action(e) raise e end; end
-class TimelogControllerTest < Test::Unit::TestCase
+class TimelogControllerTest < ActionController::TestCase
fixtures :projects, :enabled_modules, :roles, :members, :member_roles, :issues, :time_entries, :users, :trackers, :enumerations, :issue_statuses, :custom_fields, :custom_values
def setup
# Re-raise errors caught by the controller.
class TrackersController; def rescue_action(e) raise e end; end
-class TrackersControllerTest < Test::Unit::TestCase
+class TrackersControllerTest < ActionController::TestCase
fixtures :trackers, :projects, :projects_trackers, :users, :issues
def setup
# Re-raise errors caught by the controller.
class UsersController; def rescue_action(e) raise e end; end
-class UsersControllerTest < Test::Unit::TestCase
+class UsersControllerTest < ActionController::TestCase
include Redmine::I18n
fixtures :users, :projects, :members, :member_roles, :roles
# Re-raise errors caught by the controller.
class VersionsController; def rescue_action(e) raise e end; end
-class VersionsControllerTest < Test::Unit::TestCase
+class VersionsControllerTest < ActionController::TestCase
fixtures :projects, :versions, :issues, :users, :roles, :members, :member_roles, :enabled_modules
def setup
# Re-raise errors caught by the controller.
class WatchersController; def rescue_action(e) raise e end; end
-class WatchersControllerTest < Test::Unit::TestCase
+class WatchersControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules,
:issues, :trackers, :projects_trackers, :issue_statuses, :enumerations, :watchers
# Re-raise errors caught by the controller.
class WelcomeController; def rescue_action(e) raise e end; end
-class WelcomeControllerTest < Test::Unit::TestCase
+class WelcomeControllerTest < ActionController::TestCase
fixtures :projects, :news
def setup
# Re-raise errors caught by the controller.
class WikiController; def rescue_action(e) raise e end; end
-class WikiControllerTest < Test::Unit::TestCase
+class WikiControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions, :attachments
def setup
# Re-raise errors caught by the controller.
class WikisController; def rescue_action(e) raise e end; end
-class WikisControllerTest < Test::Unit::TestCase
+class WikisControllerTest < ActionController::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :wikis
def setup
# Re-raise errors caught by the controller.
class WorkflowsController; def rescue_action(e) raise e end; end
-class WorkflowsControllerTest < Test::Unit::TestCase
+class WorkflowsControllerTest < ActionController::TestCase
fixtures :roles, :trackers, :workflows
def setup
attr_accessor :request, :url
end
-class HelperTestCase < Test::Unit::TestCase
+class HelperTestCase < ActiveSupport::TestCase
# Add other helpers here if you need them
include ActionView::Helpers::ActiveRecordHelper
require File.expand_path(File.dirname(__FILE__) + '/helper_testcase')
require File.join(RAILS_ROOT,'test', 'mocks', 'open_id_authentication_mock.rb')
-class Test::Unit::TestCase
+class ActiveSupport::TestCase
# Transactional fixtures accelerate your tests by wrapping each test method
# in a transaction that's rolled back on completion. This ensures that the
# test database remains unchanged so your fixtures don't have to be reloaded
end
def test_uploaded_file(name, mime)
- ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + "/files/#{name}", mime)
+ ActionController::TestUploadedFile.new(ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime)
end
# Use a temporary directory for attachment related tests
require File.dirname(__FILE__) + '/../test_helper'
-class ActivityTest < Test::Unit::TestCase
+class ActivityTest < ActiveSupport::TestCase
fixtures :projects, :versions, :attachments, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
:trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages
require File.dirname(__FILE__) + '/../test_helper'
-class AttachmentTest < Test::Unit::TestCase
+class AttachmentTest < ActiveSupport::TestCase
fixtures :issues, :users
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class AuthSourceLdapTest < Test::Unit::TestCase
+class AuthSourceLdapTest < ActiveSupport::TestCase
def setup
end
require File.dirname(__FILE__) + '/../test_helper'
-class BoardTest < Test::Unit::TestCase
+class BoardTest < ActiveSupport::TestCase
fixtures :projects, :boards, :messages
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class CalendarTest < Test::Unit::TestCase
+class CalendarTest < ActiveSupport::TestCase
def test_monthly
c = Redmine::Helpers::Calendar.new(Date.today, :fr, :month)
require File.dirname(__FILE__) + '/../test_helper'
-class ChangesetTest < Test::Unit::TestCase
+class ChangesetTest < ActiveSupport::TestCase
fixtures :projects, :repositories, :issues, :issue_statuses, :changesets, :changes, :issue_categories, :enumerations, :custom_fields, :custom_values, :users, :members, :member_roles, :trackers
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class CommentTest < Test::Unit::TestCase
+class CommentTest < ActiveSupport::TestCase
fixtures :users, :news, :comments
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class CustomFieldTest < Test::Unit::TestCase
+class CustomFieldTest < ActiveSupport::TestCase
fixtures :custom_fields
def test_create
require File.dirname(__FILE__) + '/../test_helper'
-class CustomValueTest < Test::Unit::TestCase
+class CustomValueTest < ActiveSupport::TestCase
fixtures :custom_fields
def test_string_field_validation_with_blank_value
require File.dirname(__FILE__) + '/../test_helper'
-class DefaultDataTest < Test::Unit::TestCase
+class DefaultDataTest < ActiveSupport::TestCase
include Redmine::I18n
fixtures :roles
require File.dirname(__FILE__) + '/../test_helper'
-class DocumentCategoryTest < Test::Unit::TestCase
+class DocumentCategoryTest < ActiveSupport::TestCase
fixtures :enumerations, :documents
def test_should_be_an_enumeration
require File.dirname(__FILE__) + '/../test_helper'
-class DocumentTest < Test::Unit::TestCase
+class DocumentTest < ActiveSupport::TestCase
fixtures :projects, :enumerations, :documents
def test_create
require File.dirname(__FILE__) + '/../test_helper'
-class EnabledModuleTest < Test::Unit::TestCase
+class EnabledModuleTest < ActiveSupport::TestCase
fixtures :projects, :wikis
def test_enabling_wiki_should_create_a_wiki
require File.dirname(__FILE__) + '/../test_helper'
-class EnumerationTest < Test::Unit::TestCase
+class EnumerationTest < ActiveSupport::TestCase
fixtures :enumerations, :issues
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class FilesystemAdapterTest < Test::Unit::TestCase
+class FilesystemAdapterTest < ActiveSupport::TestCase
REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/filesystem_repository'
require File.dirname(__FILE__) + '/../test_helper'
-class GitAdapterTest < Test::Unit::TestCase
+class GitAdapterTest < ActiveSupport::TestCase
REPOSITORY_PATH = RAILS_ROOT.gsub(%r{config\/\.\.}, '') + '/tmp/test/git_repository'
if File.directory?(REPOSITORY_PATH)
require File.dirname(__FILE__) + '/../test_helper'
-class GroupTest < Test::Unit::TestCase
+class GroupTest < ActiveSupport::TestCase
fixtures :all
def test_create
require File.dirname(__FILE__) + '/../test_helper'
-class IssueCategoryTest < Test::Unit::TestCase
+class IssueCategoryTest < ActiveSupport::TestCase
fixtures :issue_categories, :issues
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class IssuePriorityTest < Test::Unit::TestCase
+class IssuePriorityTest < ActiveSupport::TestCase
fixtures :enumerations, :issues
def test_should_be_an_enumeration
require File.dirname(__FILE__) + '/../test_helper'
-class IssueStatusTest < Test::Unit::TestCase
+class IssueStatusTest < ActiveSupport::TestCase
fixtures :issue_statuses, :issues
def test_create
require File.dirname(__FILE__) + '/../test_helper'
-class IssueTest < Test::Unit::TestCase
+class IssueTest < ActiveSupport::TestCase
fixtures :projects, :users, :members, :member_roles,
:trackers, :projects_trackers,
:issue_statuses, :issue_categories, :issue_relations, :workflows,
require File.dirname(__FILE__) + '/../test_helper'
-class JournalTest < Test::Unit::TestCase
+class JournalTest < ActiveSupport::TestCase
fixtures :issues, :issue_statuses, :journals, :journal_details
def setup
require File.dirname(__FILE__) + '/../../../test_helper'
-class Redmine::AccessControlTest < Test::Unit::TestCase
+class Redmine::AccessControlTest < ActiveSupport::TestCase
def setup
@access_module = Redmine::AccessControl
require File.dirname(__FILE__) + '/../../../test_helper'
-class Redmine::Hook::ManagerTest < Test::Unit::TestCase
+class Redmine::Hook::ManagerTest < ActiveSupport::TestCase
fixtures :issues
require File.dirname(__FILE__) + '/../../../test_helper'
-class Redmine::I18nTest < Test::Unit::TestCase
+class Redmine::I18nTest < ActiveSupport::TestCase
include Redmine::I18n
def setup
require File.dirname(__FILE__) + '/../../../test_helper'
-class Redmine::MimeTypeTest < Test::Unit::TestCase
+class Redmine::MimeTypeTest < ActiveSupport::TestCase
def test_of
to_test = {'test.unk' => nil,
require File.dirname(__FILE__) + '/../../../test_helper'
-class Redmine::PluginTest < Test::Unit::TestCase
+class Redmine::PluginTest < ActiveSupport::TestCase
def setup
@klass = Redmine::Plugin
require File.dirname(__FILE__) + '/../../../test_helper'
-class Redmine::UnifiedDiffTest < Test::Unit::TestCase
+class Redmine::UnifiedDiffTest < ActiveSupport::TestCase
def setup
end
require File.dirname(__FILE__) + '/../test_helper'
-class MailHandlerTest < Test::Unit::TestCase
+class MailHandlerTest < ActiveSupport::TestCase
fixtures :users, :projects,
:enabled_modules,
:roles,
require File.dirname(__FILE__) + '/../test_helper'
-class MailerTest < Test::Unit::TestCase
+class MailerTest < ActiveSupport::TestCase
include Redmine::I18n
fixtures :projects, :issues, :users, :members, :member_roles, :documents, :attachments, :news, :tokens, :journals, :journal_details, :changesets, :trackers, :issue_statuses, :enumerations, :messages, :boards, :repositories
journal = Journal.find(2)
Mailer.deliver_issue_edit(journal)
mail = ActionMailer::Base.deliveries.last
- assert !mail.body.include?('<a href="https://mydomain.foo/issues/1">Bug #1: Can\'t print recipes</a>')
+ assert_equal 1, mail.parts.size
+ assert !mail.encoded.include?('href')
end
-
+
+ def test_html_mail
+ Setting.plain_text_mail = 0
+ journal = Journal.find(2)
+ Mailer.deliver_issue_edit(journal)
+ mail = ActionMailer::Base.deliveries.last
+ assert_equal 2, mail.parts.size
+ assert mail.encoded.include?('href')
+ end
+
def test_issue_add_message_id
ActionMailer::Base.deliveries.clear
issue = Issue.find(1)
require File.dirname(__FILE__) + '/../test_helper'
-class MemberTest < Test::Unit::TestCase
+class MemberTest < ActiveSupport::TestCase
fixtures :users, :projects, :roles, :members, :member_roles
def setup
begin
require 'mocha'
- class MercurialAdapterTest < Test::Unit::TestCase
+ class MercurialAdapterTest < ActiveSupport::TestCase
TEMPLATES_DIR = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATES_DIR
TEMPLATE_NAME = Redmine::Scm::Adapters::MercurialAdapter::TEMPLATE_NAME
require File.dirname(__FILE__) + '/../test_helper'
-class MessageTest < Test::Unit::TestCase
+class MessageTest < ActiveSupport::TestCase
fixtures :projects, :roles, :members, :member_roles, :boards, :messages, :users, :watchers
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class NewsTest < Test::Unit::TestCase
+class NewsTest < ActiveSupport::TestCase
fixtures :projects, :users, :roles, :members, :member_roles, :enabled_modules, :news
def valid_news
\r
require File.dirname(__FILE__) + '/../test_helper'\r
\r
-class ProjectTest < Test::Unit::TestCase\r
+class ProjectTest < ActiveSupport::TestCase\r
fixtures :projects, :enabled_modules, \r
:issues, :issue_statuses, :journals, :journal_details,\r
:users, :members, :member_roles, :roles, :projects_trackers, :trackers, :boards,\r
require File.dirname(__FILE__) + '/../test_helper'
-class QueryTest < Test::Unit::TestCase
+class QueryTest < ActiveSupport::TestCase
fixtures :projects, :enabled_modules, :users, :members, :member_roles, :roles, :trackers, :issue_statuses, :issue_categories, :enumerations, :issues, :watchers, :custom_fields, :custom_values, :versions, :queries
def test_custom_fields_for_all_projects_should_be_available_in_global_queries
require File.dirname(__FILE__) + '/../test_helper'
-class RepositoryBazaarTest < Test::Unit::TestCase
+class RepositoryBazaarTest < ActiveSupport::TestCase
fixtures :projects
# No '..' in the repository path
require File.dirname(__FILE__) + '/../test_helper'
require 'pp'
-class RepositoryCvsTest < Test::Unit::TestCase
+class RepositoryCvsTest < ActiveSupport::TestCase
fixtures :projects
# No '..' in the repository path
require File.dirname(__FILE__) + '/../test_helper'
-class RepositoryDarcsTest < Test::Unit::TestCase
+class RepositoryDarcsTest < ActiveSupport::TestCase
fixtures :projects
# No '..' in the repository path
require File.dirname(__FILE__) + '/../test_helper'
-class RepositoryFilesystemTest < Test::Unit::TestCase
+class RepositoryFilesystemTest < ActiveSupport::TestCase
fixtures :projects
# No '..' in the repository path
require File.dirname(__FILE__) + '/../test_helper'
-class RepositoryGitTest < Test::Unit::TestCase
+class RepositoryGitTest < ActiveSupport::TestCase
fixtures :projects
# No '..' in the repository path
require File.dirname(__FILE__) + '/../test_helper'
-class RepositoryMercurialTest < Test::Unit::TestCase
+class RepositoryMercurialTest < ActiveSupport::TestCase
fixtures :projects
# No '..' in the repository path
require File.dirname(__FILE__) + '/../test_helper'
-class RepositorySubversionTest < Test::Unit::TestCase
+class RepositorySubversionTest < ActiveSupport::TestCase
fixtures :projects
# No '..' in the repository path for svn
require File.dirname(__FILE__) + '/../test_helper'
-class RepositoryTest < Test::Unit::TestCase
+class RepositoryTest < ActiveSupport::TestCase
fixtures :projects,
:trackers,
:projects_trackers,
require File.dirname(__FILE__) + '/../test_helper'
-class RoleTest < Test::Unit::TestCase
+class RoleTest < ActiveSupport::TestCase
fixtures :roles, :workflows
def test_copy_workflows
require File.dirname(__FILE__) + '/../test_helper'
-class SearchTest < Test::Unit::TestCase
+class SearchTest < ActiveSupport::TestCase
fixtures :users,
:members,
:member_roles,
require File.dirname(__FILE__) + '/../test_helper'
-class SettingTest < Test::Unit::TestCase
+class SettingTest < ActiveSupport::TestCase
def test_read_default
assert_equal "Redmine", Setting.app_title
require File.dirname(__FILE__) + '/../test_helper'
-class SubversionAdapterTest < Test::Unit::TestCase
+class SubversionAdapterTest < ActiveSupport::TestCase
if find_executable0('svn')
def test_client_version
require File.dirname(__FILE__) + '/../test_helper'
-class TimeEntryActivityTest < Test::Unit::TestCase
+class TimeEntryActivityTest < ActiveSupport::TestCase
fixtures :enumerations, :time_entries
def test_should_be_an_enumeration
require File.dirname(__FILE__) + '/../test_helper'
-class TimeEntryTest < Test::Unit::TestCase
+class TimeEntryTest < ActiveSupport::TestCase
fixtures :issues, :projects, :users, :time_entries
def test_hours_format
require File.dirname(__FILE__) + '/../test_helper'
-class TokenTest < Test::Unit::TestCase
+class TokenTest < ActiveSupport::TestCase
fixtures :tokens
def test_create
require File.dirname(__FILE__) + '/../test_helper'
-class TrackerTest < Test::Unit::TestCase
+class TrackerTest < ActiveSupport::TestCase
fixtures :trackers, :workflows
def test_copy_workflows
require File.dirname(__FILE__) + '/../test_helper'
-class UserPreferenceTest < Test::Unit::TestCase
+class UserPreferenceTest < ActiveSupport::TestCase
fixtures :users, :user_preferences
def test_create
\r
require File.dirname(__FILE__) + '/../test_helper'\r
\r
-class UserTest < Test::Unit::TestCase\r
+class UserTest < ActiveSupport::TestCase\r
fixtures :users, :members, :projects, :roles, :member_roles\r
\r
def setup\r
require File.dirname(__FILE__) + '/../test_helper'
-class VersionTest < Test::Unit::TestCase
+class VersionTest < ActiveSupport::TestCase
fixtures :projects, :users, :issues, :issue_statuses, :trackers, :enumerations, :versions
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class WatcherTest < Test::Unit::TestCase
+class WatcherTest < ActiveSupport::TestCase
fixtures :issues, :users
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class WikiContentTest < Test::Unit::TestCase
+class WikiContentTest < ActiveSupport::TestCase
fixtures :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions, :users
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class WikiPageTest < Test::Unit::TestCase
+class WikiPageTest < ActiveSupport::TestCase
fixtures :projects, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class WikiRedirectTest < Test::Unit::TestCase
+class WikiRedirectTest < ActiveSupport::TestCase
fixtures :projects, :wikis
def setup
require File.dirname(__FILE__) + '/../test_helper'
-class WikiTest < Test::Unit::TestCase
+class WikiTest < ActiveSupport::TestCase
fixtures :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions
\r
def test_create\r
desc 'Update the plugin and tests files in the test application from the plugin'
task :mirror_engine_files => [:test_app, :copy_engines_plugin] do
- puts "> Modifying default config files to load engines plugin"
+ puts "> Tweaking generated application to be suitable for testing"
+
+ # Replace the Rails plugin loader with the engines one.
insert_line("require File.join(File.dirname(__FILE__), '../vendor/plugins/engines/boot')",
:into => 'config/environment.rb',
:after => "require File.join(File.dirname(__FILE__), 'boot')")
-
- insert_line('map.from_plugin :test_routing', :into => 'config/routes.rb',
- :after => /\AActionController::Routing::Routes/)
-
+
+ # Add the engines test helper to handle fixtures & stuff.
insert_line("require 'engines_test_helper'", :into => 'test/test_helper.rb')
+ # Run engine plugin tests when running the application
+ insert_line("task :test => ['test:engines:all']", :into => 'Rakefile')
+
+ # We want exceptions to be raised
+ insert_line("def rescue_action(e) raise e end;",
+ :into => "app/controllers/application_controller.rb",
+ :after => "class ApplicationController < ActionController::Base")
+
+ # We need this method to test where actions are being rendered from.
+ insert_line("include RenderInformation",
+ :into => "app/controllers/application_controller.rb",
+ :after => "class ApplicationController < ActionController::Base")
+
puts "> Mirroring test application files into #{test_app_dir}"
mirror_test_files('app')
mirror_test_files('lib')
summary: Enhances the plugin mechanism to perform more flexible sharing
description: The Rails Engines plugin allows the sharing of almost any type of code or asset that you could use in a Rails application, including controllers, models, stylesheets, and views.
license: MIT
-version: 2.1.0
\ No newline at end of file
+version: 2.3.2
\ No newline at end of file
begin
require 'rails/version'
- unless Rails::VERSION::MAJOR >= 2 && Rails::VERSION::MINOR >= 2 && Rails::VERSION::TINY >= 0
- raise "This version of the engines plugin requires Rails 2.2.0 or later!"
+ unless Rails::VERSION::MAJOR >= 2 && Rails::VERSION::MINOR >= 3 && Rails::VERSION::TINY >= 2
+ raise "This version of the engines plugin requires Rails 2.3.2 or later!"
end
end
# Only call Engines.init once, in the after_initialize block so that Rails
# plugin reloading works when turned on
config.after_initialize do
- Engines.init if defined? :Engines
-end
+ Engines.init(initializer) if defined? :Engines
+end
\ No newline at end of file
# List of extensions to load, can be changed in init.rb before calling Engines.init
mattr_accessor :rails_extensions
- self.rails_extensions = %w(action_mailer asset_helpers form_tag_helpers routing migrations dependencies)
+ self.rails_extensions = %w(asset_helpers form_tag_helpers migrations dependencies)
# The name of the public directory to mirror public engine assets into.
# Defaults to <tt>RAILS_ROOT/public/plugin_assets</tt>.
mattr_accessor :disable_application_code_loading
self.disable_application_code_loading = false
- # Set this ti true if code should not be mixed (i.e. it will be loaded
+ # Set this to true if code should not be mixed (i.e. it will be loaded
# from the first valid path on $LOAD_PATH)
mattr_accessor :disable_code_mixing
self.disable_code_mixing = false
self.code_mixing_file_types = %w(controller helper)
class << self
- def init
+ def init(initializer)
load_extensions
Engines::Assets.initialize_base_public_directory
end
# and that they are placed within plugin/app/things (the pluralized form of 'thing').
#
# It's important to note that you'll also want to ensure that the "things" are
- # on your load path in your plugin's init.rb:
+ # on your load path by including them in Rails load path mechanism, e.g. in init.rb:
#
- # Rails.plugins[:my_plugin].code_paths << "app/things"
+ # ActiveSupport::Dependencies.load_paths << File.join(File.dirname(__FILE__), 'app', 'things'))
#
def mix_code_from(*types)
self.code_mixing_file_types += types.map { |x| x.to_s.singularize }
#
# Engines.plugins[:plugin_name]
#
-# If this plugin contains paths in directories other than <tt>app/controllers</tt>,
-# <tt>app/helpers</tt>, <tt>app/models</tt> and <tt>components</tt>, authors can
-# declare this by adding extra paths to #code_paths:
-#
-# Rails.plugin[:my_plugin].code_paths << "app/sweepers" << "vendor/my_lib"
-#
# Other properties of the Plugin instance can also be set.
module Engines
class Plugin < Rails::Plugin
- # Plugins can add code paths to this attribute in init.rb if they
- # need plugin directories to be added to the load path, i.e.
- #
- # plugin.code_paths << 'app/other_classes'
- #
- # Defaults to ["app/controllers", "app/helpers", "app/models", "components"]
- attr_accessor :code_paths
-
# Plugins can add paths to this attribute in init.rb if they need
# controllers loaded from additional locations.
attr_accessor :controller_paths
attr_accessor :public_directory
protected
-
- # The default set of code paths which will be added to $LOAD_PATH
- # and Dependencies.load_paths
- def default_code_paths
- # lib will actually be removed from the load paths when we call
- # uniq! in #inject_into_load_paths, but it's important to keep it
- # around (for the documentation tasks, for instance).
- %w(app/controllers app/helpers app/models components lib)
- end
-
# The default set of code paths which will be added to the routing system
def default_controller_paths
%w(app/controllers components)
def initialize(directory)
super directory
- @code_paths = default_code_paths
@controller_paths = default_controller_paths
@public_directory = default_public_directory
end
- # Returns a list of paths this plugin wishes to make available in $LOAD_PATH
- #
- # Overwrites the correspondend method in the superclass
- def load_paths
- report_nonexistant_or_empty_plugin! unless valid?
- select_existing_paths :code_paths
- end
-
# Extends the superclass' load method to additionally mirror public assets
def load(initializer)
return if loaded?
super initializer
- add_plugin_view_paths
add_plugin_locale_paths
Assets.mirror_files_for(self)
end
- # for code_paths and controller_paths select those paths that actually
- # exist in the plugin's directory
+ # select those paths that actually exist in the plugin's directory
def select_existing_paths(name)
Engines.select_existing_paths(self.send(name).map { |p| File.join(directory, p) })
end
- def add_plugin_view_paths
- view_path = File.join(directory, 'app', 'views')
- if File.exist?(view_path)
- ActionController::Base.prepend_view_path(view_path) # push it just underneath the app
- end
- end
-
def add_plugin_locale_paths
locale_path = File.join(directory, 'locales')
return unless File.exists?(locale_path)
"#{File.basename(Engines.public_directory)}/#{name}"
end
- # The path to this plugin's routes file
- def routes_path
- File.join(directory, "routes.rb")
- end
-
# The directory containing this plugin's migrations (<tt>plugin/db/migrate</tt>)
def migration_directory
File.join(self.directory, 'db', 'migrate')
def register_plugin_as_loaded(plugin)
super plugin
Engines.plugins << plugin
- register_to_routing(plugin)
end
-
- # Registers the plugin's controller_paths for the routing system.
- def register_to_routing(plugin)
- initializer.configuration.controller_paths += plugin.select_existing_paths(:controller_paths)
- initializer.configuration.controller_paths.uniq!
- end
end
end
end
\ No newline at end of file
+++ /dev/null
-# The way ActionMailer is coded in terms of finding templates is very restrictive, to the point
-# where all templates for rendering must exist under the single base path. This is difficult to
-# work around without re-coding significant parts of the action mailer code.
-#
-# ---
-#
-# The MailTemplates module overrides two (private) methods from ActionMailer to enable mail
-# templates within plugins:
-#
-# [+template_path+] which now produces the contents of #template_paths
-# [+initialize_template_class+] which now find the first matching template and creates
-# an ActionVew::Base instance with the correct view_paths
-#
-# Ideally ActionMailer would use the same template-location logic as ActionView, and the same
-# view paths as ActionController::Base.view_paths, but it currently does not.
-module Engines::RailsExtensions::ActionMailer
- def self.included(base) #:nodoc:
- base.class_eval do
- alias_method_chain :template_path, :engine_additions
- alias_method_chain :initialize_template_class, :engine_additions
- end
- end
-
- private
-
- #--
- # ActionMailer::Base#create uses two mechanisms to determine the proper template file(s)
- # to load. Firstly, it searches within the template_root for files that much the explicit
- # (or implicit) part encodings (like signup.text.plain.erb for the signup action).
- # This is how implicit multipart emails are built, by the way.
- #
- # Secondly, it then creates an ActionMailer::Base instance with it's view_paths parameter
- # set to the template_root, so that ActionMailer will then take over rendering the
- # templates.
- #
- # Ideally, ActionMailer would pass the same set of view paths as it gets in a normal
- # request (i.e. ActionController::Base.view_paths), so that all possible view paths
- # were searched. However, this seems to introduce some problems with helper modules.
- #
- # So instead, and because we have to fool these two independent parts of ActionMailer,
- # we fudge with the mechanisms it uses to find the templates (via template_paths, and
- # template_path_with_engine_additions), and then intercept the creation of the ActionView
- # instance so we can set the view_paths (in initialize_template_class_with_engine_additions).
- #++
-
- # Returns all possible template paths for the current mailer, including those
- # within the loaded plugins.
- def template_paths
- paths = Engines.plugins.by_precedence.map { |p| "#{p.directory}/app/views/#{mailer_name}" }
- paths.unshift(template_path_without_engine_additions) unless Engines.disable_application_view_loading
- paths
- end
-
- # Return something that Dir[] can glob against. This method is called in
- # ActionMailer::Base#create! and used as part of an argument to Dir. We can
- # take advantage of this by using some of the features of Dir.glob to search
- # multiple paths for matching files.
- def template_path_with_engine_additions
- "{#{template_paths.join(",")}}"
- end
-
- # Return an instance of ActionView::Base with the view paths set to all paths
- # in ActionController::Base.view_paths (i.e. including all plugin view paths)
- def initialize_template_class_with_engine_additions(assigns)
- # I'd like to just return this, but I get problems finding methods in helper
- # modules if the method implemention from the regular class is not called
- #
- # ActionView::Base.new(ActionController::Base.view_paths.dup, assigns, self)
- renderer = initialize_template_class_without_engine_additions(assigns)
- renderer.view_paths.unshift(*ActionController::Base.view_paths.dup)
- renderer
- end
-end
-
-# We don't need to do this if ActionMailer hasn't been loaded.
-if Object.const_defined?(:ActionMailer)
- module ::ActionMailer #:nodoc:
- class Base #:nodoc:
- include Engines::RailsExtensions::ActionMailer
- end
- end
-end
\ No newline at end of file
+++ /dev/null
-# Effective use of Rails' routes can help create a tidy and elegant set of URLs,
-# and is a significant part of creating an external API for your web application.
-#
-# When developing plugins which contain controllers, it seems obvious that including
-# the corresponding routes would be extremely useful. This is particularly true
-# when exposing RESTful resources using the new REST-ian features of Rails.
-#
-# == Including routes in your plugin
-#
-# The engines plugin makes it possible to include a set of routes within your plugin
-# very simply, as it turns out. Include a <tt>routes.rb</tt> file like the one below
-# at the root of your plugin (along-side <tt>init.rb</tt> and <tt>lib/</tt>):
-#
-# connect "/login", :controller => "account", :action => "login"
-#
-# # add a named route
-# logout "/logout", :controller => "account", :action => "logout"
-#
-# # some restful stuff
-# resources :things do |t|
-# t.resources :other_things
-# end
-#
-# Everywhere in a normal <tt>RAILS_ROOT/config/routes.rb</tt> file
-# where you might have <tt>map.connect</tt>, you just use <tt>connect</tt> in your
-# plugin's <tt>routes.rb</tt>.
-#
-# === Hooking it up in your application
-#
-# While it would be possible to have each plugin's routes automagically included into
-# the application's route set, to do so would actually be a stunningly bad idea. Route
-# priority is the key issue here. You, the application developer, needs to be in complete
-# control when it comes to specifying the priority of routes in your application, since
-# the ordering of your routes directly affects how Rails will interpret incoming requests.
-#
-# To add plugin routes into your application's <tt>routes.rb</tt> file, you need to explicitly
-# map them in using the Engines::RailsExtensions::Routing#from_plugin method:
-#
-# ApplicationController::Routing::Routes.draw do |map|
-#
-# map.connect "/app_stuff", :controller => "application_thing" # etc...
-#
-# # This line includes the routes from the given plugin at this point, giving you
-# # control over the priority of your application routes
-# map.from_plugin :your_plugin
-#
-# map.connect ":controller/:action/:id"
-# end
-#
-# By including routes in plugins which have controllers, you can now share in a simple way
-# a compact and elegant URL scheme which corresponds to those controllers.
-#
-# ---
-#
-# The Engines::RailsExtensions::Routing module defines extensions to Rails'
-# routing (ActionController::Routing) mechanism such that routes can be loaded
-# from a given plugin.
-#
-# The key method is Engines::RailsExtensions::Routing#from_plugin, which can be called
-# within your application's <tt>config/routes.rb</tt> file to load plugin routes at that point.
-#
-module Engines::RailsExtensions::Routing
- # Loads the set of routes from within a plugin and evaluates them at this
- # point within an application's main <tt>routes.rb</tt> file.
- #
- # Plugin routes are loaded from <tt><plugin_root>/routes.rb</tt>.
- def from_plugin(name)
- map = self # to make 'map' available within the plugin route file
- routes_path = Engines.plugins[name].routes_path
- eval(IO.read(routes_path), binding, routes_path) if File.file?(routes_path)
- end
-end
-
-
-module ::ActionController #:nodoc:
- module Routing #:nodoc:
- class RouteSet #:nodoc:
- class Mapper #:nodoc:
- include Engines::RailsExtensions::Routing
- end
- end
- end
-end
# This method is called by the engines-supplied plugin testing rake tasks
def self.setup_plugin_fixtures(plugins = Engines.plugins.by_precedence)
+ # First, clear the directory
+ Dir.glob("#{self.temporary_fixtures_directory}/*.yml").each{|fixture| File.delete(fixture)}
+
# Copy all plugin fixtures, and then the application fixtures, into this directory
plugins.each do |plugin|
plugin_fixtures_directory = File.join(plugin.directory, "test", "fixtures")
- if File.directory?(plugin_fixtures_directory)
+ plugin_app_directory = File.join(plugin.directory, "app")
+ if File.directory?(plugin_app_directory) && File.directory?(plugin_fixtures_directory)
Engines.mirror_files_from(plugin_fixtures_directory, self.temporary_fixtures_directory)
end
end
ActiveSupport::TestCase.fixture_path = self.temporary_fixtures_directory
$LOAD_PATH.unshift self.temporary_fixtures_directory
end
+
+ # overridden test should be in test/{unit,functional,integration}/{plugin_name}/{test_name}
+ def self.override_tests_from_app
+ filename = caller.first.split(":").first
+ plugin_name = filename.split("/")[-4]
+ test_kind = filename.split("/")[-2]
+ override_file = File.expand_path(File.join(File.dirname(filename), "..", "..", "..", "..", "..", "test",
+ test_kind, plugin_name, File.basename(filename)))
+ load(override_file) if File.exist?(override_file)
+ end
end
\ No newline at end of file
end
desc 'Migrate a specified plugin.'
- task({:plugin => :environment}, :name, :version) do |task, args|
- name = args[:name] || ENV['NAME']
+ task(:plugin => :environment) do
+ name = ENV['NAME']
if plugin = Engines.plugins[name]
- version = args[:version] || ENV['VERSION']
+ version = ENV['VERSION']
puts "Migrating #{plugin.name} to " + (version ? "version #{version}" : 'latest version') + " ..."
plugin.migrate(version ? version.to_i : nil)
else
# this is just a modification of the original task in railties/lib/tasks/documentation.rake,
# because the default task doesn't support subdirectories like <plugin>/app or
-# <plugin>/component. These tasks now include every file under a plugin's code paths (see
-# Plugin#code_paths).
+# <plugin>/component. These tasks now include every file under a plugin's load paths (see
+# Plugin#load_paths).
namespace :doc do
plugins = FileList['vendor/plugins/**'].collect { |plugin| File.basename(plugin) }
options << '--line-numbers' << '--inline-source'
options << '-T html'
- # Include every file in the plugin's code_paths (see Plugin#code_paths)
+ # Include every file in the plugin's load_paths (see Plugin#load_paths)
if Engines.plugins[plugin]
- files.include("#{plugin_base}/{#{Engines.plugins[plugin].code_paths.join(",")}}/**/*.rb")
+ files.include("#{plugin_base}/{#{Engines.plugins[plugin].load_paths.join(",")}}/**/*.rb")
end
if File.exists?("#{plugin_base}/README")
files.include("#{plugin_base}/README")
-~===============( ... as you were ... )============================~-}
end
+ namespace :engines do
+
+ def engine_plugins
+ Dir["vendor/plugins/*"].select { |f| File.directory?(File.join(f, "app")) }.map { |f| File.basename(f) }.join(",")
+ end
+
+ desc "Run tests from within engines plugins (plugins with an 'app' directory)"
+ task :all => [:units, :functionals, :integration]
+
+ desc "Run unit tests from within engines plugins (plugins with an 'app' directory)"
+ Rake::TestTask.new(:units => "test:plugins:setup_plugin_fixtures") do |t|
+ t.pattern = "vendor/plugins/{#{ENV['PLUGIN'] || engine_plugins}}/test/unit/**/*_test.rb"
+ t.verbose = true
+ end
+
+ desc "Run functional tests from within engines plugins (plugins with an 'app' directory)"
+ Rake::TestTask.new(:functionals => "test:plugins:setup_plugin_fixtures") do |t|
+ t.pattern = "vendor/plugins/{#{ENV['PLUGIN'] || engine_plugins}}/test/functional/**/*_test.rb"
+ t.verbose = true
+ end
+
+ desc "Run integration tests from within engines plugins (plugins with an 'app' directory)"
+ Rake::TestTask.new(:integration => "test:plugins:setup_plugin_fixtures") do |t|
+ t.pattern = "vendor/plugins/{#{ENV['PLUGIN'] || engine_plugins}}/test/integration/**/*_test.rb"
+ t.verbose = true
+ end
+ end
+
namespace :plugins do
desc "Run the plugin tests in vendor/plugins/**/test (or specify with PLUGIN=name)"
--- /dev/null
+class AppAndPluginController < ApplicationController
+ def an_action
+ render_class_and_action 'from app'
+ end
+end
--- /dev/null
+class Namespace::AppAndPluginController < ApplicationController
+ def an_action
+ render_class_and_action 'from app'
+ end
+end
--- /dev/null
+module MailHelper
+ def do_something_helpful(var)
+ var.to_s.reverse
+ end
+end
\ No newline at end of file
--- /dev/null
+class AppAndPluginModel < ActiveRecord::Base
+ def self.report_location; TestHelper::report_location(__FILE__); end
+end
\ No newline at end of file
--- /dev/null
+class NotifyMail < ActionMailer::Base
+
+ helper :mail
+
+ def signup(txt)
+ body(:name => txt)
+ end
+
+ def multipart
+ recipients 'some_address@email.com'
+ subject 'multi part email'
+ from "another_user@email.com"
+ content_type 'multipart/alternative'
+
+ part :content_type => "text/html", :body => render_message("multipart_html", {})
+ part "text/plain" do |p|
+ p.body = render_message("multipart_plain", {})
+ end
+ end
+
+ def implicit_multipart
+ recipients 'some_address@email.com'
+ subject 'multi part email'
+ from "another_user@email.com"
+ end
+end
\ No newline at end of file
--- /dev/null
+class Thing
+ def self.from_app; TestHelper::report_location(__FILE__); end
+end
\ No newline at end of file
--- /dev/null
+<%= TestHelper.view_path_for __FILE__ %> (from app)
\ No newline at end of file
--- /dev/null
+<%= TestHelper.view_path_for __FILE__ %> (from app)
\ No newline at end of file
--- /dev/null
+the implicit html part of the email <%= do_something_helpful("semaj") %>
\ No newline at end of file
--- /dev/null
+the implicit plaintext part of the email
\ No newline at end of file
--- /dev/null
+the html part of the email <%= do_something_helpful("semaj") %>
\ No newline at end of file
--- /dev/null
+the plaintext part of the email
\ No newline at end of file
--- /dev/null
+Signup template from application
+
+Here's a local variable set in the Mail object: <%= @name %>.
+
+And here's a method called in a mail helper: <%= do_something_helpful(@name) %>
--- /dev/null
+<%= @note %> (from application)
\ No newline at end of file
--- /dev/null
+plugin mail template loaded from application
\ No newline at end of file
--- /dev/null
+# Tests in this file ensure that:
+#
+# * plugin controller actions are found
+# * actions defined in application controllers take precedence over those in plugins
+# * actions in controllers in subsequently loaded plugins take precendence over those in previously loaded plugins
+# * this works for actions in namespaced controllers accordingly
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ControllerLoadingTest < ActionController::TestCase
+ def setup
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ end
+
+ # plugin controller actions should be found
+
+ def test_WITH_an_action_defined_only_in_a_plugin_IT_should_use_this_action
+ get_action_on_controller :an_action, :alpha_plugin
+ assert_response_body 'rendered in AlphaPluginController#an_action'
+ end
+
+ def test_WITH_an_action_defined_only_in_a_namespaced_plugin_controller_IT_should_use_this_action
+ get_action_on_controller :an_action, :alpha_plugin, :namespace
+ assert_response_body 'rendered in Namespace::AlphaPluginController#an_action'
+ end
+
+ # app takes precedence over plugins
+
+ def test_WITH_an_action_defined_in_both_app_and_plugin_IT_should_use_the_one_in_app
+ get_action_on_controller :an_action, :app_and_plugin
+ assert_response_body 'rendered in AppAndPluginController#an_action (from app)'
+ end
+
+ def test_WITH_an_action_defined_in_namespaced_controllers_in_both_app_and_plugin_IT_should_use_the_one_in_app
+ get_action_on_controller :an_action, :app_and_plugin, :namespace
+ assert_response_body 'rendered in Namespace::AppAndPluginController#an_action (from app)'
+ end
+
+ # subsequently loaded plugins take precendence over previously loaded plugins
+
+ def test_WITH_an_action_defined_in_two_plugin_controllers_IT_should_use_the_latter_of_both
+ get_action_on_controller :an_action, :shared_plugin
+ assert_response_body 'rendered in SharedPluginController#an_action (from beta_plugin)'
+ end
+
+ def test_WITH_an_action_defined_in_two_namespaced_plugin_controllers_IT_should_use_the_latter_of_both
+ get_action_on_controller :an_action, :shared_plugin, :namespace
+ assert_response_body 'rendered in Namespace::SharedPluginController#an_action (from beta_plugin)'
+ end
+end
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ExceptionNotificationCompatibilityTest < ActionController::TestCase
+ ExceptionNotifier.exception_recipients = %w(joe@schmoe.com bill@schmoe.com)
+ class SimpleController < ApplicationController
+ include ExceptionNotifiable
+ local_addresses.clear
+ consider_all_requests_local = false
+ def index
+ begin
+ raise "Fail!"
+ rescue Exception => e
+ rescue_action_in_public(e)
+ end
+ end
+ end
+
+ def setup
+ @controller = SimpleController.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ end
+
+ def test_should_work
+ assert_nothing_raised do
+ get :index
+ end
+ end
+end
\ No newline at end of file
--- /dev/null
+# Tests in this file ensure that:
+#
+# * translations in the application take precedence over those in plugins
+# * translations in subsequently loaded plugins take precendence over those in previously loaded plugins
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class LocaleLoadingTest < ActionController::TestCase
+ def setup
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ end
+
+ # app takes precedence over plugins
+
+ def test_WITH_a_translation_defined_in_both_app_and_plugin_IT_should_find_the_one_in_app
+ assert_equal I18n.t('hello'), 'Hello world'
+ end
+
+ # subsequently loaded plugins take precendence over previously loaded plugins
+
+ def test_WITH_a_translation_defined_in_two_plugins_IT_should_find_the_latter_of_both
+ assert_equal I18n.t('plugin'), 'beta'
+ end
+end
+
--- /dev/null
+# Tests in this file ensure that:
+#
+# * Routes from plugins can be routed to
+# * Named routes can be defined within a plugin
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class RoutesTest < ActionController::TestCase
+ tests TestRoutingController
+
+ def test_WITH_a_route_defined_in_a_plugin_IT_should_route_it
+ path = '/routes/an_action'
+ opts = {:controller => 'test_routing', :action => 'an_action'}
+ assert_routing path, opts
+ assert_recognizes opts, path # not sure what exactly the difference is, but it won't hurt either
+ end
+
+ def test_WITH_a_route_for_a_namespaced_controller_defined_in_a_plugin_IT_should_route_it
+ path = 'somespace/routes/an_action'
+ opts = {:controller => 'namespace/test_routing', :action => 'an_action'}
+ assert_routing path, opts
+ assert_recognizes opts, path
+ end
+
+ def test_should_properly_generate_named_routes
+ get :test_named_routes_from_plugin
+ assert_response_body '/somespace/routes'
+ end
+end
\ No newline at end of file
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ViewHelpersTest < ActionController::TestCase
+ tests AssetsController
+
+ def setup
+ get :index
+ end
+
+ def test_plugin_javascript_helpers
+ base_selector = "script[type='text/javascript']"
+ js_dir = "/plugin_assets/test_assets/javascripts"
+ assert_select "#{base_selector}[src='#{js_dir}/file.1.js']"
+ assert_select "#{base_selector}[src='#{js_dir}/file2.js']"
+ end
+
+ def test_plugin_stylesheet_helpers
+ base_selector = "link[media='screen'][rel='stylesheet'][type='text/css']"
+ css_dir = "/plugin_assets/test_assets/stylesheets"
+ assert_select "#{base_selector}[href='#{css_dir}/file.1.css']"
+ assert_select "#{base_selector}[href='#{css_dir}/file2.css']"
+ end
+
+ def test_plugin_image_helpers
+ assert_select "img[src='/plugin_assets/test_assets/images/image.png'][alt='Image']"
+ end
+
+ def test_plugin_layouts
+ get :index
+ assert_select "div[id='assets_layout']"
+ end
+
+ def test_plugin_image_submit_helpers
+ assert_select "input[src='/plugin_assets/test_assets/images/image.png'][type='image']"
+ end
+
+end
--- /dev/null
+# Tests in this file ensure that:
+#
+# * plugin views are found
+# * views in the application take precedence over those in plugins
+# * views in subsequently loaded plugins take precendence over those in previously loaded plugins
+# * this works for namespaced views accordingly
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ViewLoadingTest < ActionController::TestCase
+ def setup
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ end
+
+ # plugin views should be found
+
+ def test_WITH_a_view_defined_only_in_a_plugin_IT_should_find_the_view
+ get_action_on_controller :a_view, :alpha_plugin
+ assert_response_body 'alpha_plugin/a_view'
+ end
+
+ def test_WITH_a_namespaced_view_defined_only_in_a_plugin_IT_should_find_the_view
+ get_action_on_controller :a_view, :alpha_plugin, :namespace
+ assert_response_body 'namespace/alpha_plugin/a_view'
+ end
+
+ # app takes precedence over plugins
+
+ def test_WITH_a_view_defined_in_both_app_and_plugin_IT_should_find_the_one_in_app
+ get_action_on_controller :a_view, :app_and_plugin
+ assert_response_body 'app_and_plugin/a_view (from app)'
+ end
+
+ def test_WITH_a_namespaced_view_defined_in_both_app_and_plugin_IT_should_find_the_one_in_app
+ get_action_on_controller :a_view, :app_and_plugin, :namespace
+ assert_response_body 'namespace/app_and_plugin/a_view (from app)'
+ end
+
+ # subsequently loaded plugins take precendence over previously loaded plugins
+
+ def test_WITH_a_view_defined_in_two_plugins_IT_should_find_the_latter_of_both
+ get_action_on_controller :a_view, :shared_plugin
+ assert_response_body 'shared_plugin/a_view (from beta_plugin)'
+ end
+
+ def test_WITH_a_namespaced_view_defined_in_two_plugins_IT_should_find_the_latter_of_both
+ get_action_on_controller :a_view, :shared_plugin, :namespace
+ assert_response_body 'namespace/shared_plugin/a_view (from beta_plugin)'
+ end
+
+ # layouts loaded from plugins
+
+ def test_should_be_able_to_load_a_layout_from_a_plugin
+ get_action_on_controller :action_with_layout, :alpha_plugin
+ assert_response_body 'rendered in AlphaPluginController#action_with_layout (with plugin layout)'
+ end
+
+end
+
\ No newline at end of file
--- /dev/null
+class AppAndPluginLibModel < ActiveRecord::Base
+ def self.report_location; TestHelper::report_location(__FILE__); end
+end
\ No newline at end of file
--- /dev/null
+module TestHelper
+ def self.report_location(path)
+ [RAILS_ROOT + '/', 'vendor/plugins/'].each { |part| path.sub! part, ''}
+ path = path.split('/')
+ location, subject = path.first, path.last
+ if subject.sub! '.rb', ''
+ subject = subject.classify
+ else
+ subject.sub! '.html.erb', ''
+ end
+ "#{subject} (from #{location})"
+ end
+
+ def self.view_path_for path
+ [RAILS_ROOT + '/', 'vendor/plugins/', '.html.erb'].each { |part| path.sub! part, ''}
+ parts = path.split('/')
+ parts[(parts.index('views')+1)..-1].join('/')
+ end
+end
+
+class Test::Unit::TestCase
+ # Add more helper methods to be used by all tests here...
+ def get_action_on_controller(*args)
+ action = args.shift
+ with_controller *args
+ get action
+ end
+
+ def with_controller(controller, namespace = nil)
+ classname = controller.to_s.classify + 'Controller'
+ classname = namespace.to_s.classify + '::' + classname unless namespace.nil?
+ @controller = classname.constantize.new
+ end
+
+ def assert_response_body(expected)
+ assert_equal expected, @response.body
+ end
+end
+
+# Because we're testing this behaviour, we actually want these features on!
+Engines.disable_application_view_loading = false
+Engines.disable_application_code_loading = false
--- /dev/null
+module RenderInformation
+ def render_class_and_action(note = nil, options={})
+ text = "rendered in #{self.class.name}##{params[:action]}"
+ text += " (#{note})" unless note.nil?
+ render options.update(:text => text)
+ end
+end
\ No newline at end of file
--- /dev/null
+class AlphaPluginController < ApplicationController
+ def an_action
+ render_class_and_action
+ end
+ def action_with_layout
+ render_class_and_action(nil, :layout => "plugin_layout")
+ end
+end
--- /dev/null
+class AppAndPluginController < ApplicationController
+ def an_action
+ render_class_and_action 'from alpha_plugin'
+ end
+end
--- /dev/null
+class Namespace::AlphaPluginController < ApplicationController
+ def an_action
+ render_class_and_action
+ end
+end
\ No newline at end of file
--- /dev/null
+class Namespace::AppAndPluginController < ApplicationController
+ def an_action
+ render_class_and_action 'from alpha_plugin'
+ end
+end
--- /dev/null
+class Namespace::SharedPluginController < ApplicationController
+ def an_action
+ render_class_and_action 'from alpha_plugin'
+ end
+end
--- /dev/null
+class SharedEngineController < ApplicationController
+ def an_action
+ render_class_and_action 'from alpha_engine'
+ end
+end
--- /dev/null
+class AlphaPluginModel < ActiveRecord::Base
+ def self.report_location; TestHelper::report_location(__FILE__); end
+end
\ No newline at end of file
--- /dev/null
+class AppAndPluginModel < ActiveRecord::Base
+ def self.report_location; TestHelper::report_location(__FILE__); end
+
+ def defined_only_in_alpha_plugin_version
+ # should not be defined as the model in app/models takes precedence
+ end
+end
\ No newline at end of file
--- /dev/null
+class SharedPluginModel < ActiveRecord::Base
+ def self.report_location; TestHelper::report_location(__FILE__); end
+end
\ No newline at end of file
--- /dev/null
+<%= TestHelper.view_path_for __FILE__ %>
\ No newline at end of file
--- /dev/null
+<%= TestHelper.view_path_for __FILE__ %> (from a_view)
\ No newline at end of file
--- /dev/null
+<%= yield %> (with plugin layout)
\ No newline at end of file
--- /dev/null
+<%= TestHelper.view_path_for __FILE__ %>
\ No newline at end of file
--- /dev/null
+<%= TestHelper.view_path_for __FILE__ %>
\ No newline at end of file
--- /dev/null
+<%= TestHelper.view_path_for __FILE__ %> (from alpha_plugin)
\ No newline at end of file
--- /dev/null
+<%= TestHelper.view_path_for __FILE__ %> (from alpha_plugin)
\ No newline at end of file
--- /dev/null
+class AlphaPluginLibModel < ActiveRecord::Base
+ def self.report_location; TestHelper::report_location(__FILE__); end
+end
\ No newline at end of file
--- /dev/null
+class AppAndPluginLibModel < ActiveRecord::Base
+ def self.report_location; TestHelper::report_location(__FILE__); end
+
+ def defined_only_in_alpha_plugin_version
+ # should not be defined
+ end
+end
\ No newline at end of file
--- /dev/null
+en:
+ hello: "Hello from alfa"
+ plugin: "alfa"
--- /dev/null
+class AppAndPluginController < ApplicationController
+ def an_action
+ render_class_and_action 'from beta_plugin'
+ end
+end
--- /dev/null
+class Namespace::SharedPluginController < ApplicationController
+ def an_action
+ render_class_and_action 'from beta_plugin'
+ end
+end
--- /dev/null
+class SharedPluginController < ApplicationController
+ def an_action
+ render_class_and_action 'from beta_plugin'
+ end
+end
--- /dev/null
+class SharedPluginModel < ActiveRecord::Base
+ def self.report_location; TestHelper::report_location(__FILE__); end
+end
\ No newline at end of file
--- /dev/null
+<%= TestHelper.view_path_for __FILE__ %> (from beta_plugin)
\ No newline at end of file
--- /dev/null
+<%= TestHelper.view_path_for __FILE__ %> (from beta_plugin)
\ No newline at end of file
--- /dev/null
+# just here so that Rails recognizes this as a plugin
\ No newline at end of file
--- /dev/null
+en:
+ hello: "Hello from beta"
+ plugin: "beta"
--- /dev/null
+class AssetsController < ApplicationController
+end
\ No newline at end of file
--- /dev/null
+<%= image_tag 'image.png', :plugin => 'test_assets' %>
+<%= javascript_include_tag 'file.1.js', 'file2', :plugin => "test_assets" %>
+<%= stylesheet_link_tag 'file.1.css', 'file2', :plugin => "test_assets" %>
+<%= image_submit_tag 'image.png', :plugin => "test_assets" %>
--- /dev/null
+<div id="assets_layout">
+ <%= yield %>
+</div>
\ No newline at end of file
--- /dev/null
+class Thing
+ def self.from_plugin; TestHelper::report_location(__FILE__); end
+end
\ No newline at end of file
--- /dev/null
+# just here so that Rails recognizes this as a plugin
\ No newline at end of file
--- /dev/null
+class CreateTests < ActiveRecord::Migration
+ def self.up
+ create_table 'tests' do |t|
+ t.column 'name', :string
+ end
+ end
+
+ def self.down
+ drop_table 'tests'
+ end
+end
--- /dev/null
+class CreateOthers < ActiveRecord::Migration
+ def self.up
+ create_table 'others' do |t|
+ t.column 'name', :string
+ end
+ end
+
+ def self.down
+ drop_table 'others'
+ end
+end
--- /dev/null
+class CreateExtras < ActiveRecord::Migration
+ def self.up
+ create_table 'extras' do |t|
+ t.column 'name', :string
+ end
+ end
+
+ def self.down
+ drop_table 'extras'
+ end
+end
--- /dev/null
+class PluginMail < ActionMailer::Base
+ def mail_from_plugin(note=nil)
+ body(:note => note)
+ end
+
+ def mail_from_plugin_with_application_template(note=nil)
+ body(:note => note)
+ end
+
+ def multipart_from_plugin
+ content_type 'multipart/alternative'
+ part :content_type => "text/html", :body => render_message("multipart_from_plugin_html", {})
+ part "text/plain" do |p|
+ p.body = render_message("multipart_from_plugin_plain", {})
+ end
+ end
+
+ def multipart_from_plugin_with_application_template
+ content_type 'multipart/alternative'
+ part :content_type => "text/html", :body => render_message("multipart_from_plugin_with_application_template_html", {})
+ part "text/plain" do |p|
+ p.body = render_message("multipart_from_plugin_with_application_template_plain", {})
+ end
+ end
+
+end
\ No newline at end of file
--- /dev/null
+<%= @note %>
\ No newline at end of file
--- /dev/null
+html template
\ No newline at end of file
--- /dev/null
+plain template
\ No newline at end of file
--- /dev/null
+template from plugin
\ No newline at end of file
--- /dev/null
+template from plugin
\ No newline at end of file
--- /dev/null
+class Namespace::TestRoutingController < ApplicationController
+ def routed_action
+ render_class_and_action
+ end
+end
\ No newline at end of file
--- /dev/null
+class TestRoutingController < ApplicationController
+ def routed_action
+ render_class_and_action
+ end
+
+ def test_named_routes_from_plugin
+ render :text => plugin_route_path(:action => "index")
+ end
+end
\ No newline at end of file
--- /dev/null
+ActionController::Routing::Routes.draw do |map|
+ map.connect 'routes/:action', :controller => "test_routing"
+ map.plugin_route 'somespace/routes/:action', :controller => "namespace/test_routing"
+end
\ No newline at end of file
--- /dev/null
+Fixtures are only copied from plugins with an +app+ directory, but git needs this directory to be non-empty
\ No newline at end of file
--- /dev/null
+require File.expand_path(File.join(File.dirname(__FILE__), *%w[.. .. .. .. .. test test_helper]))
+
+class OverrideTest < ActiveSupport::TestCase
+ def test_overrides_from_the_application_should_work
+ flunk "this test should be overridden by the app"
+ end
+
+ def test_tests_within_the_plugin_should_still_run
+ assert true, "non-overridden plugin tests should still run"
+ end
+end
+
+Engines::Testing.override_tests_from_app
\ No newline at end of file
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ActionMailerWithinApplicationTest < Test::Unit::TestCase
+
+ def test_normal_implicit_template
+ m = NotifyMail.create_signup("hello")
+ assert m.body =~ /^Signup template from application/
+ end
+
+ def test_action_mailer_can_get_helper
+ m = NotifyMail.create_signup('James')
+ assert m.body =~ /James/
+ assert m.body =~ /semaJ/ # from the helper
+ end
+
+ def test_multipart_mails_with_explicit_templates
+ m = NotifyMail.create_multipart
+ assert_equal 2, m.parts.length
+ assert_equal 'the html part of the email james', m.parts[0].body
+ assert_equal 'the plaintext part of the email', m.parts[1].body
+ end
+
+ def test_multipart_mails_with_implicit_templates
+ m = NotifyMail.create_implicit_multipart
+ assert_equal 2, m.parts.length
+ assert_equal 'the implicit plaintext part of the email', m.parts[0].body
+ assert_equal 'the implicit html part of the email james', m.parts[1].body
+ end
+end
+
+
+class ActionMailerWithinPluginsTest < Test::Unit::TestCase
+ def test_should_be_able_to_create_mails_from_plugin
+ m = PluginMail.create_mail_from_plugin("from_plugin")
+ assert_equal "from_plugin", m.body
+ end
+
+ def test_should_be_able_to_overload_views_within_the_application
+ m = PluginMail.create_mail_from_plugin_with_application_template("from_plugin")
+ assert_equal "from_plugin (from application)", m.body
+ end
+
+ def test_should_be_able_to_create_a_multipart_mail_from_within_plugin
+ m = PluginMail.create_multipart_from_plugin
+ assert_equal 2, m.parts.length
+ assert_equal 'html template', m.parts[0].body
+ assert_equal 'plain template', m.parts[1].body
+ end
+
+ def test_plugin_mailer_template_overriding
+ m = PluginMail.create_multipart_from_plugin_with_application_template
+ assert_equal 'plugin mail template loaded from application', m.parts[1].body
+ end
+end
\ No newline at end of file
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ArbitraryCodeMixingTest < Test::Unit::TestCase
+ def setup
+ Engines.code_mixing_file_types = %w(controller helper)
+ end
+
+ def test_should_allow_setting_of_different_code_mixing_file_types
+ assert_nothing_raised {
+ Engines.mix_code_from :things
+ }
+ end
+
+ def test_should_add_new_types_to_existing_code_mixing_file_types
+ Engines.mix_code_from :things
+ assert_equal ["controller", "helper", "thing"], Engines.code_mixing_file_types
+ Engines.mix_code_from :other
+ assert_equal ["controller", "helper", "thing", "other"], Engines.code_mixing_file_types
+ end
+
+ def test_should_allow_setting_of_multiple_types_at_once
+ Engines.mix_code_from :things, :other
+ assert_equal ["controller", "helper", "thing", "other"], Engines.code_mixing_file_types
+ end
+
+ def test_should_singularize_elements_to_be_mixed
+ # this is the only test using mocha, so let's try to work around it
+ # also, this seems to be already tested with the :things in the tests above
+ # arg = stub(:to_s => stub(:singularize => "element"))
+ Engines.mix_code_from :elements
+ assert Engines.code_mixing_file_types.include?("element")
+ end
+
+ # TODO doesn't seem to work as expected?
+
+ # def test_should_successfully_mix_custom_types
+ # Engines.mix_code_from :things
+ # assert_equal 'Thing (from app)', Thing.from_app
+ # assert_equal 'Thing (from test_code_mixing)', Thing.from_plugin
+ # end
+end
\ No newline at end of file
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+
+class AssetsTest < Test::Unit::TestCase
+ def setup
+ Engines::Assets.mirror_files_for Engines.plugins[:test_assets]
+ end
+
+ def teardown
+ FileUtils.rm_r(Engines.public_directory) if File.exist?(Engines.public_directory)
+ end
+
+ def test_engines_has_created_base_public_file
+ assert File.exist?(Engines.public_directory)
+ end
+
+ def test_engines_has_created_README_in_public_directory
+ assert File.exist?(File.join(Engines.public_directory, 'README'))
+ end
+
+ def test_public_files_have_been_copied_from_test_assets_plugin
+ assert File.exist?(File.join(Engines.public_directory, 'test_assets'))
+ assert File.exist?(File.join(Engines.public_directory, 'test_assets', 'file.txt'))
+ assert File.exist?(File.join(Engines.public_directory, 'test_assets', 'subfolder'))
+ assert File.exist?(File.join(Engines.public_directory, 'test_assets', 'subfolder', 'file_in_subfolder.txt'))
+ end
+
+ def test_engines_has_not_created_duplicated_file_structure
+ assert !File.exists?(File.join(Engines.public_directory, "test_assets", RAILS_ROOT))
+ end
+
+ def test_public_files_have_been_copied_from_test_assets_with_assets_dir_plugin
+ Engines::Assets.mirror_files_for Engines.plugins[:test_assets_with_assets_directory]
+
+ assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_assets_directory'))
+ assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_assets_directory', 'file.txt'))
+ assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_assets_directory', 'subfolder'))
+ assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_assets_directory', 'subfolder', 'file_in_subfolder.txt'))
+ end
+
+ def test_public_files_have_been_copied_from_test_assets_with_no_subdirectory_plugin
+ Engines::Assets.mirror_files_for Engines.plugins[:test_assets_with_no_subdirectory]
+
+ assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_no_subdirectory'))
+ assert File.exist?(File.join(Engines.public_directory, 'test_assets_with_no_subdirectory', 'file.txt'))
+ end
+
+ def test_public_files_have_NOT_been_copied_from_plugins_without_public_or_asset_directories
+ Engines::Assets.mirror_files_for Engines.plugins[:alpha_plugin]
+
+ assert !File.exist?(File.join(Engines.public_directory, 'alpha_plugin'))
+ end
+end
\ No newline at end of file
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+
+class BackwardsCompatibilityTest < Test::Unit::TestCase
+ def test_rails_module_plugin_method_should_delegate_to_engines_plugins
+ assert_nothing_raised { Rails.plugins }
+ assert_equal Engines.plugins, Rails.plugins
+ end
+end
\ No newline at end of file
--- /dev/null
+# Tests in this file ensure that:
+#
+# * the application /app/[controllers|helpers|models] and /lib
+# paths preceed the corresponding plugin paths
+# * the plugin paths are added to $LOAD_PATH in the order in which plugins are
+# loaded
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class LoadPathTest < Test::Unit::TestCase
+ def setup
+ @load_path = expand_paths($LOAD_PATH)
+ end
+
+ # Not sure if these test actually make sense as this now essentially tests
+ # Rails core functionality. On the other hand Engines relies on this to some
+ # extend so this will choke if something important changes in Rails.
+
+ # the application app/... and lib/ directories should appear
+ # before any plugin directories
+
+ def test_application_app_libs_should_precede_all_plugin_app_libs
+ types = %w(app/controllers app/helpers app/models lib)
+ types.each do |t|
+ app_index = load_path_index(File.join(RAILS_ROOT, t))
+ assert_not_nil app_index, "#{t} is missing in $LOAD_PATH"
+ Engines.plugins.each do |plugin|
+ first_plugin_index = load_path_index(File.join(plugin.directory, t))
+ assert(app_index < first_plugin_index) unless first_plugin_index.nil?
+ end
+ end
+ end
+
+ # the engine directories should appear in the proper order based on
+ # the order they were started
+
+ def test_plugin_dirs_should_appear_in_reverse_plugin_loading_order
+ app_paths = %w(app/controllers/ app app/models app/helpers lib)
+ app_paths.map { |p| File.join(RAILS_ROOT, p)}
+ plugin_paths = Engines.plugins.reverse.collect { |plugin| plugin.load_paths.reverse }.flatten
+
+ expected_paths = expand_paths(app_paths + plugin_paths)
+ # only look at those paths that are also present in expected_paths so
+ # the only difference would be in the order of the paths
+ actual_paths = @load_path & expected_paths
+
+ assert_equal expected_paths, actual_paths
+ end
+
+ protected
+ def expand_paths(paths)
+ paths.collect { |p| File.expand_path(p) }
+ end
+
+ def load_path_index(dir)
+ @load_path.index(File.expand_path(dir))
+ end
+end
\ No newline at end of file
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+require 'rails_generator'
+require 'rails_generator/scripts/generate'
+
+class MigrationsTest < Test::Unit::TestCase
+
+ @@migration_dir = "#{RAILS_ROOT}/db/migrate"
+
+ def setup
+ ActiveRecord::Migration.verbose = false
+ Engines.plugins[:test_migration].migrate(0)
+ end
+
+ def teardown
+ FileUtils.rm_r(@@migration_dir) if File.exist?(@@migration_dir)
+ end
+
+ def test_engine_migrations_can_run_down
+ assert !table_exists?('tests'), ActiveRecord::Base.connection.tables.inspect
+ assert !table_exists?('others'), ActiveRecord::Base.connection.tables.inspect
+ assert !table_exists?('extras'), ActiveRecord::Base.connection.tables.inspect
+ end
+
+ def test_engine_migrations_can_run_up
+ Engines.plugins[:test_migration].migrate(3)
+ assert table_exists?('tests')
+ assert table_exists?('others')
+ assert table_exists?('extras')
+ end
+
+ def test_engine_migrations_can_upgrade_incrementally
+ Engines.plugins[:test_migration].migrate(1)
+ assert table_exists?('tests')
+ assert !table_exists?('others')
+ assert !table_exists?('extras')
+ assert_equal 1, Engines::Plugin::Migrator.current_version(Engines.plugins[:test_migration])
+
+
+ Engines.plugins[:test_migration].migrate(2)
+ assert table_exists?('others')
+ assert_equal 2, Engines::Plugin::Migrator.current_version(Engines.plugins[:test_migration])
+
+
+ Engines.plugins[:test_migration].migrate(3)
+ assert table_exists?('extras')
+ assert_equal 3, Engines::Plugin::Migrator.current_version(Engines.plugins[:test_migration])
+ end
+
+ def test_generator_creates_plugin_migration_file
+ Rails::Generator::Scripts::Generate.new.run(['plugin_migration', 'test_migration'], :quiet => true)
+ assert migration_file, "migration file is missing"
+ end
+
+ private
+
+ def table_exists?(table)
+ ActiveRecord::Base.connection.tables.include?(table)
+ end
+
+ def migration_file
+ Dir["#{@@migration_dir}/*test_migration_to_version_3.rb"][0]
+ end
+end
\ No newline at end of file
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+
+class ModelAndLibTest < Test::Unit::TestCase
+
+ def test_WITH_a_model_defined_only_in_a_plugin_IT_should_load_the_model
+ assert_equal 'AlphaPluginModel (from alpha_plugin)', AlphaPluginModel.report_location
+ end
+
+ def test_WITH_a_model_defined_only_in_a_plugin_lib_dir_IT_should_load_the_model
+ assert_equal 'AlphaPluginLibModel (from alpha_plugin)', AlphaPluginLibModel.report_location
+ end
+
+ # app takes precedence over plugins
+
+ def test_WITH_a_model_defined_in_both_app_and_plugin_IT_should_load_the_one_in_app
+ assert_equal 'AppAndPluginModel (from app)', AppAndPluginModel.report_location
+ assert_raises(NoMethodError) { AppAndPluginLibModel.defined_only_in_alpha_engine_version }
+ end
+
+ def test_WITH_a_model_defined_in_both_app_and_plugin_lib_dirs_IT_should_load_the_one_in_app
+ assert_equal 'AppAndPluginLibModel (from lib)', AppAndPluginLibModel.report_location
+ assert_raises(NoMethodError) { AppAndPluginLibModel.defined_only_in_alpha_engine_version }
+ end
+
+ # subsequently loaded plugins take precendence over previously loaded plugins
+
+ # TODO
+ #
+ # this does work when we rely on $LOAD_PATH while it won't work when we use
+ # Dependency constant autoloading. This somewhat confusing difference has
+ # been there since at least Rails 1.2.x. See http://www.ruby-forum.com/topic/134529
+
+ def test_WITH_a_model_defined_in_two_plugins_IT_should_load_the_latter_of_both
+ require 'shared_plugin_model'
+ assert_equal SharedPluginModel.report_location, 'SharedPluginModel (from beta_plugin)'
+ end
+end
\ No newline at end of file
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+
+class PluginsTest < Test::Unit::TestCase
+
+ def test_should_allow_access_to_plugins_by_strings_or_symbols
+ p = Engines.plugins["alpha_plugin"]
+ q = Engines.plugins[:alpha_plugin]
+ assert_kind_of Engines::Plugin, p
+ assert_equal p, q
+ end
+end
\ No newline at end of file
--- /dev/null
+require File.join(File.dirname(__FILE__), *%w[.. .. test_helper])
+
+class OverrideTest < ActiveSupport::TestCase
+ def test_overrides_from_the_application_should_work
+ assert true, "overriding plugin tests from the application should work"
+ end
+end
\ No newline at end of file
--- /dev/null
+require File.dirname(__FILE__) + '/../test_helper'
+
+class TestingTest < Test::Unit::TestCase
+ def setup
+ Engines::Testing.set_fixture_path
+ @filename = File.join(Engines::Testing.temporary_fixtures_directory, 'testing_fixtures.yml')
+ File.delete(@filename) if File.exists?(@filename)
+ end
+
+ def teardown
+ File.delete(@filename) if File.exists?(@filename)
+ end
+
+ def test_should_copy_fixtures_files_to_tmp_directory
+ assert !File.exists?(@filename)
+ Engines::Testing.setup_plugin_fixtures
+ assert File.exists?(@filename)
+ end
+end
\ No newline at end of file
--- /dev/null
+module PrependEngineViews
+ def self.included(base)
+ base.send(:include, InstanceMethods)
+ base.class_eval do
+ alias_method_chain :add_engine_view_paths, :prepend
+ end
+ end
+
+ module InstanceMethods
+ # Patch Rails so engine's views are prepended to the view_path,
+ # thereby letting plugins override application views
+ def add_engine_view_paths_with_prepend
+ paths = ActionView::PathSet.new(engines.collect(&:view_path))
+ ActionController::Base.view_paths.unshift(*paths)
+ ActionMailer::Base.view_paths.unshift(*paths) if configuration.frameworks.include?(:action_mailer)
+ end
+ end
+end
+
+Rails::Plugin::Loader.send :include, PrependEngineViews
+