diff --git a/README.rdoc b/README.rdoc deleted file mode 100644 index 7c36f235..00000000 --- a/README.rdoc +++ /dev/null @@ -1,261 +0,0 @@ -== Welcome to Rails - -Rails is a web-application framework that includes everything needed to create -database-backed web applications according to the Model-View-Control pattern. - -This pattern splits the view (also called the presentation) into "dumb" -templates that are primarily responsible for inserting pre-built data in between -HTML tags. The model contains the "smart" domain objects (such as Account, -Product, Person, Post) that holds all the business logic and knows how to -persist themselves to a database. The controller handles the incoming requests -(such as Save New Account, Update Product, Show Post) by manipulating the model -and directing data to the view. - -In Rails, the model is handled by what's called an object-relational mapping -layer entitled Active Record. This layer allows you to present the data from -database rows as objects and embellish these data objects with business logic -methods. You can read more about Active Record in -link:files/vendor/rails/activerecord/README.html. - -The controller and view are handled by the Action Pack, which handles both -layers by its two parts: Action View and Action Controller. These two layers -are bundled in a single package due to their heavy interdependence. This is -unlike the relationship between the Active Record and Action Pack that is much -more separate. Each of these packages can be used independently outside of -Rails. You can read more about Action Pack in -link:files/vendor/rails/actionpack/README.html. - - -== Getting Started - -1. At the command prompt, create a new Rails application: - rails new myapp (where myapp is the application name) - -2. Change directory to myapp and start the web server: - cd myapp; rails server (run with --help for options) - -3. Go to http://localhost:3000/ and you'll see: - "Welcome aboard: You're riding Ruby on Rails!" - -4. Follow the guidelines to start developing your application. You can find -the following resources handy: - -* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html -* Ruby on Rails Tutorial Book: http://www.railstutorial.org/ - - -== Debugging Rails - -Sometimes your application goes wrong. Fortunately there are a lot of tools that -will help you debug it and get it back on the rails. - -First area to check is the application log files. Have "tail -f" commands -running on the server.log and development.log. Rails will automatically display -debugging and runtime information to these files. Debugging info will also be -shown in the browser on requests from 127.0.0.1. - -You can also log your own messages directly into the log file from your code -using the Ruby logger class from inside your controllers. Example: - - class WeblogController < ActionController::Base - def destroy - @weblog = Weblog.find(params[:id]) - @weblog.destroy - logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!") - end - end - -The result will be a message in your log file along the lines of: - - Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1! - -More information on how to use the logger is at http://www.ruby-doc.org/core/ - -Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are -several books available online as well: - -* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe) -* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide) - -These two books will bring you up to speed on the Ruby language and also on -programming in general. - - -== Debugger - -Debugger support is available through the debugger command when you start your -Mongrel or WEBrick server with --debugger. This means that you can break out of -execution at any point in the code, investigate and change the model, and then, -resume execution! You need to install ruby-debug to run the server in debugging -mode. With gems, use sudo gem install ruby-debug. Example: - - class WeblogController < ActionController::Base - def index - @posts = Post.all - debugger - end - end - -So the controller will accept the action, run the first line, then present you -with a IRB prompt in the server window. Here you can do things like: - - >> @posts.inspect - => "[#nil, "body"=>nil, "id"=>"1"}>, - #"Rails", "body"=>"Only ten..", "id"=>"2"}>]" - >> @posts.first.title = "hello from a debugger" - => "hello from a debugger" - -...and even better, you can examine how your runtime objects actually work: - - >> f = @posts.first - => #nil, "body"=>nil, "id"=>"1"}> - >> f. - Display all 152 possibilities? (y or n) - -Finally, when you're ready to resume execution, you can enter "cont". - - -== Console - -The console is a Ruby shell, which allows you to interact with your -application's domain model. Here you'll have all parts of the application -configured, just like it is when the application is running. You can inspect -domain models, change values, and save to the database. Starting the script -without arguments will launch it in the development environment. - -To start the console, run rails console from the application -directory. - -Options: - -* Passing the -s, --sandbox argument will rollback any modifications - made to the database. -* Passing an environment name as an argument will load the corresponding - environment. Example: rails console production. - -To reload your controllers and models after launching the console run -reload! - -More information about irb can be found at: -link:http://www.rubycentral.org/pickaxe/irb.html - - -== dbconsole - -You can go to the command line of your database directly through rails -dbconsole. You would be connected to the database with the credentials -defined in database.yml. Starting the script without arguments will connect you -to the development database. Passing an argument will connect you to a different -database, like rails dbconsole production. Currently works for MySQL, -PostgreSQL and SQLite 3. - -== Description of Contents - -The default directory structure of a generated Ruby on Rails application: - - |-- app - | |-- assets - | |-- images - | |-- javascripts - | `-- stylesheets - | |-- controllers - | |-- helpers - | |-- mailers - | |-- models - | `-- views - | `-- layouts - |-- config - | |-- environments - | |-- initializers - | `-- locales - |-- db - |-- doc - |-- lib - | `-- tasks - |-- log - |-- public - |-- script - |-- test - | |-- fixtures - | |-- functional - | |-- integration - | |-- performance - | `-- unit - |-- tmp - | |-- cache - | |-- pids - | |-- sessions - | `-- sockets - `-- vendor - |-- assets - `-- stylesheets - `-- plugins - -app - Holds all the code that's specific to this particular application. - -app/assets - Contains subdirectories for images, stylesheets, and JavaScript files. - -app/controllers - Holds controllers that should be named like weblogs_controller.rb for - automated URL mapping. All controllers should descend from - ApplicationController which itself descends from ActionController::Base. - -app/models - Holds models that should be named like post.rb. Models descend from - ActiveRecord::Base by default. - -app/views - Holds the template files for the view that should be named like - weblogs/index.html.erb for the WeblogsController#index action. All views use - eRuby syntax by default. - -app/views/layouts - Holds the template files for layouts to be used with views. This models the - common header/footer method of wrapping views. In your views, define a layout - using the layout :default and create a file named default.html.erb. - Inside default.html.erb, call <% yield %> to render the view using this - layout. - -app/helpers - Holds view helpers that should be named like weblogs_helper.rb. These are - generated for you automatically when using generators for controllers. - Helpers can be used to wrap functionality for your views into methods. - -config - Configuration files for the Rails environment, the routing map, the database, - and other dependencies. - -db - Contains the database schema in schema.rb. db/migrate contains all the - sequence of Migrations for your schema. - -doc - This directory is where your application documentation will be stored when - generated using rake doc:app - -lib - Application specific libraries. Basically, any kind of custom code that - doesn't belong under controllers, models, or helpers. This directory is in - the load path. - -public - The directory available for the web server. Also contains the dispatchers and the - default HTML files. This should be set as the DOCUMENT_ROOT of your web - server. - -script - Helper scripts for automation and generation. - -test - Unit and functional tests along with fixtures. When using the rails generate - command, template test files will be generated for you and placed in this - directory. - -vendor - External libraries that the application depends on. Also includes the plugins - subdirectory. If the app has frozen rails, those gems also go here, under - vendor/rails/. This directory is in the load path. diff --git a/app/controllers/data_controller.rb b/app/controllers/data_controller.rb index 8a530451..a38726a3 100644 --- a/app/controllers/data_controller.rb +++ b/app/controllers/data_controller.rb @@ -18,7 +18,7 @@ class DataController < ApplicationController def yaml_export all_tables = {} - all_tables['todos'] = current_user.todos.includes(:tags) + all_tables['todos'] = current_user.todos.includes(:tags).all all_tables['contexts'] = current_user.contexts.all all_tables['projects'] = current_user.projects.all @@ -37,10 +37,10 @@ class DataController < ApplicationController tags = Tag.where("id IN (?) OR id IN (?)", todo_tag_ids, rec_todo_tag_ids) taggings = Tagging.where("tag_id IN (?) OR tag_id IN(?)", todo_tag_ids, rec_todo_tag_ids) - all_tables['tags'] = tags - all_tables['taggings'] = taggings - all_tables['notes'] = current_user.notes - all_tables['recurring_todos'] = current_user.recurring_todos + all_tables['tags'] = tags.all + all_tables['taggings'] = taggings.all + all_tables['notes'] = current_user.notes.all + all_tables['recurring_todos'] = current_user.recurring_todos.all result = all_tables.to_yaml result.gsub!(/\n/, "\r\n") # TODO: general functionality for line endings @@ -72,13 +72,13 @@ class DataController < ApplicationController def csv_notes content_type = 'text/csv' - CSV::Writer.generate(result = "") do |csv| + CSV.generate(result = "") do |csv| csv << ["id", "User ID", "Project", "Note", "Created at", "Updated at"] # had to remove project include because it's association order is leaking # through and causing an ambiguous column ref even with_exclusive_scope # didn't seem to help -JamesKebinger - current_user.notes.order("notes.created_at").each do |note| + current_user.notes.reorder("notes.created_at").each do |note| # Format dates in ISO format for easy sorting in spreadsheet Print # context and project names for easy viewing csv << [note.id, note.user_id, diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 06ad7edc..273c3d0a 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -113,7 +113,7 @@ class ProjectsController < ApplicationController @done = {} @done = @project.todos.completed. - order("todos.completed_at DESC"). + reorder("todos.completed_at DESC"). limit(current_user.prefs.show_number_completed). includes(Todo::DEFAULT_INCLUDES) unless current_user.prefs.show_number_completed == 0 diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index d7804887..3137c92b 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -10,12 +10,12 @@ class SearchController < ApplicationController @found_not_complete_todos = current_user.todos. where("(todos.description LIKE ? OR todos.notes LIKE ?) AND todos.completed_at IS NULL", terms, terms). includes(Todo::DEFAULT_INCLUDES). - order("todos.due IS NULL, todos.due ASC, todos.created_at ASC") + reorder("todos.due IS NULL, todos.due ASC, todos.created_at ASC") @found_complete_todos = current_user.todos. where("(todos.description LIKE ? OR todos.notes LIKE ?) AND NOT (todos.completed_at IS NULL)", terms, terms). includes(Todo::DEFAULT_INCLUDES). - order("todos.completed_at DESC") + reorder("todos.completed_at DESC") @found_todos = @found_not_complete_todos + @found_complete_todos diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb index 863c3a28..b1e2b099 100644 --- a/app/controllers/stats_controller.rb +++ b/app/controllers/stats_controller.rb @@ -6,10 +6,10 @@ class StatsController < ApplicationController def index @page_title = t('stats.index_title') + @first_action = current_user.todos.reorder("created_at ASC").first @tags_count = get_total_number_of_tags_of_user @unique_tags_count = get_unique_tags_of_user.size @hidden_contexts = current_user.contexts.hidden - @first_action = current_user.todos.order("created_at ASC").first get_stats_actions get_stats_contexts @@ -55,8 +55,8 @@ class StatsController < ApplicationController end def actions_done_lastyears_data - @actions_done_last_months = current_user.todos.completed.select("completed_at").order("completed_at DESC") - @actions_created_last_months = current_user.todos.select("created_at").order("created_at DESC" ) + @actions_done_last_months = current_user.todos.completed.select("completed_at").reorder("completed_at DESC") + @actions_created_last_months = current_user.todos.select("created_at").reorder("created_at DESC" ) # query is sorted, so use last todo to calculate number of months @month_count = [difference_in_months(@today, @actions_created_last_months.last.created_at), @@ -101,7 +101,7 @@ class StatsController < ApplicationController end def actions_completion_time_data - @actions_completion_time = current_user.todos.completed.select("completed_at, created_at").order("completed_at DESC" ) + @actions_completion_time = current_user.todos.completed.select("completed_at, created_at").reorder("completed_at DESC" ) # convert to array and fill in non-existing weeks with 0 @max_weeks = difference_in_weeks(@today, @actions_completion_time.last.completed_at) @@ -121,7 +121,7 @@ class StatsController < ApplicationController end def actions_running_time_data - @actions_running_time = current_user.todos.not_completed.select("created_at").order("created_at DESC") + @actions_running_time = current_user.todos.not_completed.select("created_at").reorder("created_at DESC") # convert to array and fill in non-existing weeks with 0 @max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at) @@ -151,7 +151,7 @@ class StatsController < ApplicationController @actions_running_time = current_user.todos.not_completed.not_hidden.not_deferred_or_blocked. select("todos.created_at"). - order("todos.created_at DESC") + reorder("todos.created_at DESC") @max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at) @actions_running_per_week_array = convert_to_weeks_from_today_array(@actions_running_time, @max_weeks+1, :created_at) @@ -172,7 +172,7 @@ class StatsController < ApplicationController def actions_open_per_week_data @actions_started = current_user.todos.created_after(@today-53.weeks). select("todos.created_at, todos.completed_at"). - order("todos.created_at DESC") + reorder("todos.created_at DESC") @max_weeks = difference_in_weeks(@today, @actions_started.last.created_at) @@ -358,7 +358,7 @@ class StatsController < ApplicationController # get all running actions that are visible @actions_running_time = current_user.todos.not_completed.not_hidden.not_deferred_or_blocked. select("todos.id, todos.created_at"). - order("todos.created_at DESC") + reorder("todos.created_at DESC") selected_todo_ids = get_ids_from(@actions_running_time, week_from, week_to, params['id']== 'avrt_end') @selected_actions = selected_todo_ids.size == 0 ? [] : current_user.todos.where("id in (" + selected_todo_ids.join(",") + ")") @@ -399,10 +399,10 @@ class StatsController < ApplicationController init_not_done_counts - @done_recently = current_user.todos.completed.limit(10).order('completed_at DESC').includes(Todo::DEFAULT_INCLUDES) - @last_completed_projects = current_user.projects.completed.limit(10).order('completed_at DESC').includes(:todos, :notes) + @done_recently = current_user.todos.completed.limit(10).reorder('completed_at DESC').includes(Todo::DEFAULT_INCLUDES) + @last_completed_projects = current_user.projects.completed.limit(10).reorder('completed_at DESC').includes(:todos, :notes) @last_completed_contexts = [] - @last_completed_recurring_todos = current_user.recurring_todos.completed.limit(10).order('completed_at DESC').includes(:tags, :taggings) + @last_completed_recurring_todos = current_user.recurring_todos.completed.limit(10).reorder('completed_at DESC').includes(:tags, :taggings) #TODO: @last_completed_contexts = current_user.contexts.completed.all(:limit => 10, :order => 'completed_at DESC') end diff --git a/app/controllers/todos_controller.rb b/app/controllers/todos_controller.rb index 895db3fb..97cb80a4 100644 --- a/app/controllers/todos_controller.rb +++ b/app/controllers/todos_controller.rb @@ -1,36 +1,152 @@ class TodosController < ApplicationController - helper :todos - skip_before_filter :login_required, :only => [:index, :calendar, :tag] prepend_before_filter :login_or_feed_token_required, :only => [:index, :calendar, :tag] append_before_filter :find_and_activate_ready, :only => [:index, :list_deferred] - # TODO: replace :except with :only - append_before_filter :init, :except => [ :tag, :tags, :destroy, :done, - :check_deferred, :toggle_check, :toggle_star, :edit, :update, :defer, :create, - :calendar, :auto_complete_for_predecessor, :remove_predecessor, :add_predecessor] + # # TODO: replace :except with :only + # append_before_filter :init, :except => [ :tag, :tags, :destroy, :done, + # :check_deferred, :toggle_check, :toggle_star, :edit, :update, :defer, :create, + # :calendar, :auto_complete_for_predecessor, :remove_predecessor, :add_predecessor] protect_from_forgery :except => :check_deferred - # these are needed for todo_feed_content. TODO: remove this view stuff from controller - include ActionView::Helpers::SanitizeHelper - extend ActionView::Helpers::SanitizeHelper::ClassMethods + # # these are needed for todo_feed_content. TODO: remove this view stuff from controller + # include ActionView::Helpers::SanitizeHelper + # extend ActionView::Helpers::SanitizeHelper::ClassMethods + def with_feed_query_scope(&block) + unless TodosController.is_feed_request(request) + Todo.send(:where, ['todos.state = ?', 'active']) do + yield + return + end + end + condition_builder = FindConditionBuilder.new + + if params.key?('done') + condition_builder.add 'todos.state = ?', 'completed' + else + condition_builder.add 'todos.state = ?', 'active' + end + + @title = t('todos.next_actions_title') + @description = t('todos.next_actions_description') + + if params.key?('due') + due_within = params['due'].to_i + due_within_when = Time.zone.now + due_within.days + condition_builder.add('todos.due <= ?', due_within_when) + due_within_date_s = due_within_when.strftime("%Y-%m-%d") + @title << t('todos.next_actions_title_additions.due_today') if (due_within == 0) + @title << t('todos.next_actions_title_additions.due_within_a_week') if (due_within == 6) + @description << t('todos.next_actions_description_additions.due_date', :due_date => due_within_date_s) + end + + if params.key?('done') + done_in_last = params['done'].to_i + condition_builder.add('todos.completed_at >= ?', Time.zone.now - done_in_last.days) + @title << t('todos.next_actions_title_additions.completed') + @description << t('todos.next_actions_description_additions.completed', :count => done_in_last.to_s) + end + + if params.key?('tag') + tag = Tag.find_by_name(params['tag']) + if tag.nil? + tag = Tag.new(:name => params['tag']) + end + condition_builder.add('taggings.tag_id = ?', tag.id) + end + + Todo.send :where, condition_builder.to_conditions do + yield + end + + end + + def with_parent_resource_scope(&block) + @feed_title = t('common.actions') + if (params[:context_id]) + @context = current_user.contexts.find_by_params(params) + @feed_title = @feed_title + t('todos.feed_title_in_context', :context => @context.name) + Todo.send :where, ['todos.context_id = ?', @context.id] do + yield + end + elsif (params[:project_id]) + @project = current_user.projects.find_by_params(params) + @feed_title = @feed_title + t('todos.feed_title_in_project', :project => @project.name) + @project_feed = true + Todo.send :where, ['todos.project_id = ?', @project.id] do + yield + end + else + yield + end + end + + def with_limit_scope(&block) + if params.key?('limit') + Todo.send :with_scope, :find => { :limit => params['limit'] } do + yield + end + if TodosController.is_feed_request(request) && @description + if params.key?('limit') + @description << t('todos.list_incomplete_next_actions_with_limit', :count => params['limit']) + else + @description << t('todos.list_incomplete_next_actions') + end + end + else + yield + end + end + def index + @source_view = params['_source_view'] || 'todo' + init_data_for_sidebar unless mobile? + + if mobile? + @not_done_todos = current_user.todos. + where('todos.state = ? AND contexts.hide = ? AND (projects.state = ? OR todos.project_id IS NULL)', 'active', false, 'active'). + reorder("todos.due IS NULL, todos.due ASC, todos.created_at ASC"). + includes(:project, :context, :tags) + else + @todos = current_user.todos.includes(Todo::DEFAULT_INCLUDES) + @not_done_todos = current_user.todos. + where('contexts.hide = ? AND (projects.state = ? OR todos.project_id IS NULL)', false, 'active'). + reorder("todos.due IS NULL, todos.due ASC, todos.created_at ASC"). + includes(Todo::DEFAULT_INCLUDES) + end + @projects = current_user.projects.includes(:default_context) @contexts = current_user.contexts - @contexts_to_show = current_user.contexts.active + + # If you've set no_completed to zero, the completed items box isn't shown + # on the home page + max_completed = current_user.prefs.show_number_completed + @done = current_user.todos.completed.limit(max_completed).includes(Todo::DEFAULT_INCLUDES) unless max_completed == 0 respond_to do |format| - format.html &render_todos_html - format.m &render_todos_mobile + format.html do + @page_title = t('todos.task_list_title') + # Set count badge to number of not-done, not hidden context items + @count = current_user.todos.active.not_hidden.count(:all) + end + format.m do + @page_title = t('todos.mobile_todos_page_title') + @home = true + + cookies[:mobile_url]= { :value => request.request_uri, :secure => SITE_CONFIG['secure_cookies']} + determine_down_count + + render :action => 'index' + end format.xml { render :xml => @todos.to_xml( *to_xml_params ) } - format.rss &render_rss_feed - format.atom &render_atom_feed - format.text &render_text_feed - format.ics &render_ical_feed + format.rss + format.atom + format.text + format.ics end end @@ -315,7 +431,7 @@ class TodosController < ApplicationController # Toggles the 'done' status of the action # def toggle_check - @todo = current_user.todos.find_by_id(params['id']) + @todo = current_user.todos.find(params['id']) @source_view = params['_source_view'] || 'todo' @original_item_due = @todo.due @original_item_was_deferred = @todo.deferred? @@ -565,7 +681,7 @@ class TodosController < ApplicationController @source_view = 'done' @page_title = t('todos.completed_tasks_title') - @done = current_user.todos.completed.includes(Todo::DEFAULT_INCLUDES).order('completed_at DESC').paginate :page => params[:page], :per_page => 20 + @done = current_user.todos.completed.includes(Todo::DEFAULT_INCLUDES).reorder('completed_at DESC').paginate :page => params[:page], :per_page => 20 @count = @done.size end @@ -624,26 +740,26 @@ class TodosController < ApplicationController @not_done_todos = todos_with_tag_ids. active.not_hidden. - order('todos.due IS NULL, todos.due ASC, todos.created_at ASC'). + reorder('todos.due IS NULL, todos.due ASC, todos.created_at ASC'). includes(Todo::DEFAULT_INCLUDES) @hidden_todos = todos_with_tag_ids. hidden. - order('todos.completed_at DESC, todos.created_at DESC'). + reorder('todos.completed_at DESC, todos.created_at DESC'). includes(Todo::DEFAULT_INCLUDES) @deferred = todos_with_tag_ids. deferred. - order('todos.show_from ASC, todos.created_at DESC'). + reorder('todos.show_from ASC, todos.created_at DESC'). includes(Todo::DEFAULT_INCLUDES) @pending = todos_with_tag_ids. blocked. - order('todos.show_from ASC, todos.created_at DESC'). + reorder('todos.show_from ASC, todos.created_at DESC'). includes(Todo::DEFAULT_INCLUDES) # If you've set no_completed to zero, the completed items box isn't shown on # the tag page @done = todos_with_tag_ids.completed. limit(current_user.prefs.show_number_completed). - order('todos.completed_at DESC'). + reorder('todos.completed_at DESC'). includes(Todo::DEFAULT_INCLUDES) @projects = current_user.projects @@ -696,7 +812,7 @@ class TodosController < ApplicationController @tag = Tag.find_by_name(@tag_name) @tag = Tag.new(:name => @tag_name) if @tag.nil? - @done = current_user.todos.completed.with_tag(@tag.id).order('completed_at DESC').includes(Todo::DEFAULT_INCLUDES).paginate :page => params[:page], :per_page => 20 + @done = current_user.todos.completed.with_tag(@tag.id).reorder('completed_at DESC').includes(Todo::DEFAULT_INCLUDES).paginate :page => params[:page], :per_page => 20 @count = @done.size render :template => 'todos/all_done' end @@ -772,34 +888,34 @@ class TodosController < ApplicationController @due_today = current_user.todos.not_completed. where('todos.due <= ?', due_today_date). includes(included_tables). - order("due") + reorder("due") @due_this_week = current_user.todos.not_completed. where('todos.due > ? AND todos.due <= ?', due_today_date, due_this_week_date). includes(included_tables). - order("due") + reorder("due") @due_next_week = current_user.todos.not_completed. where('todos.due > ? AND todos.due <= ?', due_this_week_date, due_next_week_date). includes(included_tables). - order("due") + reorder("due") @due_this_month = current_user.todos.not_completed. where('todos.due > ? AND todos.due <= ?', due_next_week_date, due_this_month_date). includes(included_tables). - order("due") + reorder("due") @due_after_this_month = current_user.todos.not_completed. where('todos.due > ?', due_this_month_date). includes(included_tables). - order("due") + reorder("due") @count = current_user.todos.not_completed.are_due.count respond_to do |format| format.html format.ics { - @due_all = current_user.todos.not_completed.are_due.order("due") + @due_all = current_user.todos.not_completed.are_due.reorder("due") render :action => 'calendar', :layout => false, :content_type => Mime::ICS } format.xml { - @due_all = current_user.todos.not_completed.are_due.order("due") + @due_all = current_user.todos.not_completed.are_due.reorder("due") render :xml => @due_all.to_xml( *to_xml_params ) } end @@ -821,26 +937,26 @@ class TodosController < ApplicationController @items = @todo.project.todos.not_completed. where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id). includes(:context, :project). - order('description ASC'). + reorder('description ASC'). limit(10) unless @todo.project.nil? # Then look in the current context, excluding @todo itself @items = @todo.context.todos.not_completed where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id). includes(:context, :project). - order('description ASC'). + reorder('description ASC'). limit(10) unless !@items.empty? || @todo.context.nil? # Match todos in other projects, excluding @todo itself @items = current_user.todos.not_completed. where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id). includes(:context, :project). - order('description ASC'). + reorder('description ASC'). limit(10) unless !@items.empty? else # New todo - TODO: Filter on current project in project view @items = current_user.todos.not_completed. where('(LOWER(todos.description) LIKE ?)', "%#{params[:term].downcase}%"). includes(:context, :project). - order('description ASC'). + reorder('description ASC'). limit(10) end render :inline => format_dependencies_as_json_for_auto_complete(@items) @@ -894,136 +1010,6 @@ class TodosController < ApplicationController current_user.deferred_todos.find_and_activate_ready end - def init - @source_view = params['_source_view'] || 'todo' - init_data_for_sidebar unless mobile? - init_todos - end - - def with_feed_query_scope(&block) - unless TodosController.is_feed_request(request) - Todo.send(:where, ['todos.state = ?', 'active']) do - yield - return - end - end - condition_builder = FindConditionBuilder.new - - if params.key?('done') - condition_builder.add 'todos.state = ?', 'completed' - else - condition_builder.add 'todos.state = ?', 'active' - end - - @title = t('todos.next_actions_title') - @description = t('todos.next_actions_description') - - if params.key?('due') - due_within = params['due'].to_i - due_within_when = Time.zone.now + due_within.days - condition_builder.add('todos.due <= ?', due_within_when) - due_within_date_s = due_within_when.strftime("%Y-%m-%d") - @title << t('todos.next_actions_title_additions.due_today') if (due_within == 0) - @title << t('todos.next_actions_title_additions.due_within_a_week') if (due_within == 6) - @description << t('todos.next_actions_description_additions.due_date', :due_date => due_within_date_s) - end - - if params.key?('done') - done_in_last = params['done'].to_i - condition_builder.add('todos.completed_at >= ?', Time.zone.now - done_in_last.days) - @title << t('todos.next_actions_title_additions.completed') - @description << t('todos.next_actions_description_additions.completed', :count => done_in_last.to_s) - end - - if params.key?('tag') - tag = Tag.find_by_name(params['tag']) - if tag.nil? - tag = Tag.new(:name => params['tag']) - end - condition_builder.add('taggings.tag_id = ?', tag.id) - end - - Todo.send :where, condition_builder.to_conditions do - yield - end - - end - - def with_parent_resource_scope(&block) - @feed_title = t('common.actions') - if (params[:context_id]) - @context = current_user.contexts.find_by_params(params) - @feed_title = @feed_title + t('todos.feed_title_in_context', :context => @context.name) - Todo.send :where, ['todos.context_id = ?', @context.id] do - yield - end - elsif (params[:project_id]) - @project = current_user.projects.find_by_params(params) - @feed_title = @feed_title + t('todos.feed_title_in_project', :project => @project.name) - @project_feed = true - Todo.send :where, ['todos.project_id = ?', @project.id] do - yield - end - else - yield - end - end - - def with_limit_scope(&block) - if params.key?('limit') - Todo.send :with_scope, :find => { :limit => params['limit'] } do - yield - end - if TodosController.is_feed_request(request) && @description - if params.key?('limit') - @description << t('todos.list_incomplete_next_actions_with_limit', :count => params['limit']) - else - @description << t('todos.list_incomplete_next_actions') - end - end - else - yield - end - end - - def init_todos - with_feed_query_scope do - with_parent_resource_scope do # @context or @project may get defined here - with_limit_scope do - - if mobile? - init_todos_for_mobile_view - else - - # Note: these next two finds were previously using - # current_users.todos.find but that broke with_scope for :limit - - # Exclude hidden projects from count on home page - @todos = current_user.todos.includes(Todo::DEFAULT_INCLUDES) - - # Exclude hidden projects from the home page - @not_done_todos = current_user.todos. - where('contexts.hide = ? AND (projects.state = ? OR todos.project_id IS NULL)', false, 'active'). - order("todos.due IS NULL, todos.due ASC, todos.created_at ASC"). - includes(Todo::DEFAULT_INCLUDES) - end - - end - end - end - end - - def init_todos_for_mobile_view - # Note: these next two finds were previously using current_users.todos.find - # but that broke with_scope for :limit - - # Exclude hidden projects from the home page - @not_done_todos = current_user.todos. - where('todos.state = ? AND contexts.hide = ? AND (projects.state = ? OR todos.project_id IS NULL)', 'active', false, 'active'). - order("todos.due IS NULL, todos.due ASC, todos.created_at ASC"). - includes(:project, :context, :tags) - end - def tag_title(tag_expr) and_list = tag_expr.inject([]) { |s,tag_list| s << tag_list.join(',') } return and_list.join(' AND ') @@ -1194,99 +1180,6 @@ class TodosController < ApplicationController @remaining_deferred_or_pending_count = tag.nil? ? 0 : current_user.todos.deferred.with_tag(tag.id).count end - def render_todos_html - lambda do - @page_title = t('todos.task_list_title') - - # If you've set no_completed to zero, the completed items box isn't shown - # on the home page - max_completed = current_user.prefs.show_number_completed - @done = current_user.todos.completed.limit(max_completed).includes(Todo::DEFAULT_INCLUDES) unless max_completed == 0 - - # Set count badge to number of not-done, not hidden context items - @count = current_user.todos.active.not_hidden.count(:all) - - render - end - end - - def render_todos_mobile - lambda do - @page_title = t('todos.mobile_todos_page_title') - @home = true - - max_completed = current_user.prefs.show_number_completed - @done = current_user.todos.completed.limit(max_completed).includes(Todo::DEFAULT_INCLUDES) unless max_completed == 0 - - cookies[:mobile_url]= { :value => request.request_uri, :secure => SITE_CONFIG['secure_cookies']} - determine_down_count - - render :action => 'index' - end - end - - def render_rss_feed - lambda do - render_rss_feed_for @todos, :feed => todo_feed_options, - :item => { - :title => :description, - :link => lambda { |t| @project_feed.nil? ? context_url(t.context) : project_url(t.project) }, - :guid => lambda { |t| todo_url(t) }, - :description => todo_feed_content - } - end - end - - def todo_feed_options - options = Todo.feed_options(current_user) - options[:title] = @feed_title - return options - end - - def todo_feed_content - # TODO: move view stuff into view, also the includes at the top - lambda do |i| - item_notes = i.rendered_notes if i.notes? - due = "
#{t('todos.feeds.due', :date => format_date(i.due))}
\n" if i.due? - done = "
#{t('todos.feeds.completed', :date => format_date(i.completed_at))}
\n" if i.completed? - context_link = "#{ i.context.name }" - if i.project_id? - project_link = "#{ i.project.name }" - else - project_link = "#{t('common.none')}" - end - "#{done||''}#{due||''}#{item_notes||''}\n
#{t('common.project')}: #{project_link}
\n
#{t('common.context')}: #{context_link}
" - end - end - - def render_atom_feed - lambda do - render_atom_feed_for @todos, :feed => todo_feed_options, - :item => { - :title => :description, - :link => lambda { |t| context_url(t.context) }, - :description => todo_feed_content, - :author => lambda { |p| nil } - } - end - end - - def render_text_feed - lambda do - render :action => 'index', :layout => false, :content_type => Mime::TEXT - end - end - - def render_ical_feed - lambda do - render :action => 'index', :layout => false, :content_type => Mime::ICS - end - end - - def self.is_feed_request(req) - ['rss','atom','txt','ics'].include?(req.parameters[:format]) - end - def check_for_next_todo(todo) # check if this todo has a related recurring_todo. If so, create next todo new_recurring_todo = nil @@ -1434,7 +1327,7 @@ class TodosController < ApplicationController begin params["todo"]["due"] = parse_date_per_user_prefs(params["todo"]["due"]) rescue - @todo.errors.add_to_base("Invalid due date") + @todo.errors[:base] << "Invalid due date" end else params["todo"]["due"] = "" @@ -1443,7 +1336,7 @@ class TodosController < ApplicationController begin params['todo']['show_from'] = parse_date_per_user_prefs(params['todo']['show_from']) rescue - @todo.errors.add_to_base("Invalid show from date") + @todo.errors[:base] << "Invalid show from date" end end end @@ -1530,23 +1423,84 @@ class TodosController < ApplicationController return !( all_list_uniq_ids.length == all_list_count ) end - - class FindConditionBuilder - - def initialize - @queries = Array.new - @params = Array.new - end - - def add(query, param) - @queries << query - @params << param - end - - def to_conditions - [@queries.join(' AND ')] + @params - end - end + + # def render_text_feed + # lambda do + # render :action => 'index', :layout => false, :content_type => Mime::TEXT + # end + # end + # + # def render_ical_feed + # lambda do + # render :action => 'index', :layout => false, :content_type => Mime::ICS + # end + # end + # + # def self.is_feed_request(req) + # ['rss','atom','txt','ics'].include?(req.parameters[:format]) + # end + # + # class FindConditionBuilder + # + # def initialize + # @queries = Array.new + # @params = Array.new + # end + # + # def add(query, param) + # @queries << query + # @params << param + # end + # + # def to_conditions + # [@queries.join(' AND ')] + @params + # end + # end + # def render_rss_feed + # lambda do + # render_rss_feed_for @todos, :feed => todo_feed_options, + # :item => { + # :title => :description, + # :link => lambda { |t| @project_feed.nil? ? context_url(t.context) : project_url(t.project) }, + # :guid => lambda { |t| todo_url(t) }, + # :description => todo_feed_content + # } + # end + # end + # + # def todo_feed_options + # options = Todo.feed_options(current_user) + # options[:title] = @feed_title + # return options + # end + # + # def todo_feed_content + # # TODO: move view stuff into view, also the includes at the top + # lambda do |i| + # item_notes = i.rendered_notes if i.notes? + # due = "
#{t('todos.feeds.due', :date => format_date(i.due))}
\n" if i.due? + # done = "
#{t('todos.feeds.completed', :date => format_date(i.completed_at))}
\n" if i.completed? + # context_link = "#{ i.context.name }" + # if i.project_id? + # project_link = "#{ i.project.name }" + # else + # project_link = "#{t('common.none')}" + # end + # "#{done||''}#{due||''}#{item_notes||''}\n
#{t('common.project')}: #{project_link}
\n
#{t('common.context')}: #{context_link}
" + # end + # end + # + # def render_atom_feed + # lambda do + # render_atom_feed_for @todos, :feed => todo_feed_options, + # :item => { + # :title => :description, + # :link => lambda { |t| context_url(t.context) }, + # :description => todo_feed_content, + # :author => lambda { |p| nil } + # } + # end + # end class TodoCreateParamsHelper diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 44f8ac0d..9174dfbc 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -26,7 +26,7 @@ class UsersController < ApplicationController # GET /users/id GET /users/id.xml def show - @user = User.find_by_id(params[:id]) + @user = User.find(params[:id]) render :xml => @user.to_xml(:except => [ :password ]) end @@ -83,7 +83,7 @@ class UsersController < ApplicationController user.auth_type == 'ldap' && !SimpleLdapAuthenticator.valid?(user.login, params['user']['password']) notify :warning, "Incorrect password" - redirect_to :action => 'new' + redirect_to signup_path return end @@ -137,7 +137,7 @@ class UsersController < ApplicationController # DELETE /users/id DELETE /users/id.xml def destroy - @deleted_user = User.find_by_id(params[:id]) + @deleted_user = User.find(params[:id]) @saved = @deleted_user.destroy @total_users = User.all.size @@ -155,19 +155,18 @@ class UsersController < ApplicationController end end - def change_password @page_title = t('users.change_password_title') end def update_password # is used for focing password change after sha->bcrypt upgrade - @user.change_password(params[:user][:password], params[:user][:password_confirmation]) + current_user.change_password(params[:user][:password], params[:user][:password_confirmation]) notify :notice, t('users.password_updated') redirect_to preferences_path rescue Exception => error notify :error, error.message - redirect_to :action => 'change_password' + redirect_to change_password_user_path(current_user) end def change_auth_type @@ -175,40 +174,19 @@ class UsersController < ApplicationController end def update_auth_type - if (params[:open_id_complete] || (params[:user][:auth_type] == 'open_id')) && openid_enabled? - authenticate_with_open_id do |result, identity_url| - if result.successful? - # Success means that the transaction completed without error. If info - # is nil, it means that the user cancelled the verification. - @user.auth_type = 'open_id' - @user.open_id_url = identity_url - if @user.save - notify :notice, t('users.openid_url_verified', :url => identity_url) - else - debugger - notify :warning, t('users.openid_ok_pref_failed', :url => identity_url) - end - redirect_to preferences_path - else - notify :warning, result.message - redirect_to :action => 'change_auth_type' - end - end - return - end - @user.auth_type = params[:user][:auth_type] - if @user.save + current_user.auth_type = params[:user][:auth_type] + if current_user.save notify :notice, t('users.auth_type_updated') redirect_to preferences_path else - notify :warning, t('users.auth_type_update_error', :error_messages => @user.errors.full_messages.join(', ')) - redirect_to :action => 'change_auth_type' + notify :warning, t('users.auth_type_update_error', :error_messages => current_user.errors.full_messages.join(', ')) + redirect_to change_auth_type_user_path(current_user) end end def refresh_token - @user.generate_token - @user.save! + current_user.generate_token + current_user.save! notify :notice, t('users.new_token_generated') redirect_to preferences_path end diff --git a/app/models/message_gateway.rb b/app/models/message_gateway.rb index 69a924b8..e3a4adc8 100644 --- a/app/models/message_gateway.rb +++ b/app/models/message_gateway.rb @@ -1,37 +1,25 @@ class MessageGateway < ActionMailer::Base - # include ActionView::Helpers::SanitizeHelper - # extend ActionView::Helpers::SanitizeHelper::ClassMethods + include ActionView::Helpers::SanitizeHelper + extend ActionView::Helpers::SanitizeHelper::ClassMethods def receive(email) - puts "email = #{email}" - address = '' - if SITE_CONFIG['email_dispatch'] == 'to' - address = email.to[0] - else - address = email.from[0] - end - - user = User.where("preferences.sms_email" => address.strip).first(:include => [:preference]) - if user.nil? - user = User.where("preferences.sms_email" => address.strip[1.100]).first(:include => [:preference]) - end + user = get_user_from_email_address(email) return if user.nil? + context = user.prefs.sms_context - description = nil notes = nil - - if email.content_type == "multipart/related" - description = sanitize email.subject - body_part = email.parts.find{|m| m.content_type == "text/plain"} - notes = sanitize body_part.body.strip + + if email.multipart? + description = get_text_or_nil(email.subject) + notes = get_first_text_plain_part(email) else - if email.subject && email.subject.blank? - description = sanitize email.body.strip + if email.subject.blank? + description = get_decoded_text_or_nil(email.body) notes = nil else - description = sanitize email.subject.strip - notes = sanitize email.body.strip + description = get_text_or_nil(email.subject) + notes = get_decoded_text_or_nil(email.body) end end @@ -41,4 +29,33 @@ class MessageGateway < ActionMailer::Base todo = Todo.from_rich_message(user, context.id, description, notes) todo.save! end + + private + + def get_address(email) + return SITE_CONFIG['email_dispatch'] == 'to' ? email.to[0] : email.from[0] + end + + def get_user_from_email_address(email) + address = get_address(email) + user = User.where("preferences.sms_email" => address.strip).includes(:preference).first + if user.nil? + user = User.where("preferences.sms_email" => address.strip[1.100]).includes(:preference).first + end + return user + end + + def get_text_or_nil(text) + return text ? sanitize(text.strip) : nil + end + + def get_decoded_text_or_nil(text) + return text ? sanitize(text.decoded.strip) : nil + end + + def get_first_text_plain_part(email) + parts = email.parts.reject{|part| !part.content_type.start_with?("text/plain") } + return parts ? sanitize(parts[0].decoded.strip) : "" + end + end diff --git a/app/models/preference.rb b/app/models/preference.rb index 1fdbf26a..2a51e542 100644 --- a/app/models/preference.rb +++ b/app/models/preference.rb @@ -3,7 +3,7 @@ class Preference < ActiveRecord::Base belongs_to :sms_context, :class_name => 'Context' attr_accessible :date_format, :week_starts, :show_number_completed, :show_completed_projects_in_sidebar, - :show_hidden_contexts_in_sidebar, :staleness_starts, :due_style, :admin_email + :show_hidden_contexts_in_sidebar, :staleness_starts, :due_style, :admin_email, :locale def self.due_styles { :due_in_n_days => 0, :due_on => 1} diff --git a/app/models/recurring_todo.rb b/app/models/recurring_todo.rb index 869750d8..8826d07c 100644 --- a/app/models/recurring_todo.rb +++ b/app/models/recurring_todo.rb @@ -51,30 +51,30 @@ class RecurringTodo < ActiveRecord::Base def validate_daily if (!only_work_days) && (daily_every_x_days.nil? || daily_every_x_days.blank?) - errors.add_to_base("Every other nth day may not be empty for recurrence setting") + errors[:base] << "Every other nth day may not be empty for recurrence setting" end end def validate_weekly if weekly_every_x_week.nil? || weekly_every_x_week.blank? - errors.add_to_base("Every other nth week may not be empty for recurrence setting") + errors[:base] << "Every other nth week may not be empty for recurrence setting" end something_set = false %w{sunday monday tuesday wednesday thursday friday saturday}.each do |day| something_set ||= self.send("on_#{day}") end - errors.add_to_base("You must specify at least one day on which the todo recurs") if !something_set + errors[:base] << "You must specify at least one day on which the todo recurs" if !something_set end def validate_monthly case recurrence_selector when 0 # 'monthly_every_x_day' - errors.add_to_base("The day of the month may not be empty for recurrence setting") if monthly_every_x_day.nil? || monthly_every_x_day.blank? - errors.add_to_base("Every other nth month may not be empty for recurrence setting") if monthly_every_x_month.nil? || monthly_every_x_month.blank? + errors[:base] << "The day of the month may not be empty for recurrence setting" if monthly_every_x_day.nil? || monthly_every_x_day.blank? + errors[:base] << "Every other nth month may not be empty for recurrence setting" if monthly_every_x_month.nil? || monthly_every_x_month.blank? when 1 # 'monthly_every_xth_day' - errors.add_to_base("Every other nth month may not be empty for recurrence setting") if monthly_every_x_month2.nil? || monthly_every_x_month2.blank? - errors.add_to_base("The nth day of the month may not be empty for recurrence setting") if monthly_every_xth_day.nil? || monthly_every_xth_day.blank? - errors.add_to_base("The day of the month may not be empty for recurrence setting") if monthly_day_of_week.nil? || monthly_day_of_week.blank? + errors[:base] <<"Every other nth month may not be empty for recurrence setting" if monthly_every_x_month2.nil? || monthly_every_x_month2.blank? + errors[:base] <<"The nth day of the month may not be empty for recurrence setting" if monthly_every_xth_day.nil? || monthly_every_xth_day.blank? + errors[:base] <<"The day of the month may not be empty for recurrence setting" if monthly_day_of_week.nil? || monthly_day_of_week.blank? else raise Exception.new, "unexpected value of recurrence selector '#{self.recurrence_selector}'" end @@ -83,26 +83,26 @@ class RecurringTodo < ActiveRecord::Base def validate_yearly case recurrence_selector when 0 # 'yearly_every_x_day' - errors.add_to_base("The month of the year may not be empty for recurrence setting") if yearly_month_of_year.nil? || yearly_month_of_year.blank? - errors.add_to_base("The day of the month may not be empty for recurrence setting") if yearly_every_x_day.nil? || yearly_every_x_day.blank? + errors[:base] << "The month of the year may not be empty for recurrence setting" if yearly_month_of_year.nil? || yearly_month_of_year.blank? + errors[:base] << "The day of the month may not be empty for recurrence setting" if yearly_every_x_day.nil? || yearly_every_x_day.blank? when 1 # 'yearly_every_xth_day' - errors.add_to_base("The month of the year may not be empty for recurrence setting") if yearly_month_of_year2.nil? || yearly_month_of_year2.blank? - errors.add_to_base("The nth day of the month may not be empty for recurrence setting") if yearly_every_xth_day.nil? || yearly_every_xth_day.blank? - errors.add_to_base("The day of the week may not be empty for recurrence setting") if yearly_day_of_week.nil? || yearly_day_of_week.blank? + errors[:base] << "The month of the year may not be empty for recurrence setting" if yearly_month_of_year2.nil? || yearly_month_of_year2.blank? + errors[:base] << "The nth day of the month may not be empty for recurrence setting" if yearly_every_xth_day.nil? || yearly_every_xth_day.blank? + errors[:base] << "The day of the week may not be empty for recurrence setting" if yearly_day_of_week.nil? || yearly_day_of_week.blank? else raise Exception.new, "unexpected value of recurrence selector '#{self.recurrence_selector}'" end end def starts_and_ends_on_validations - errors.add_to_base("The start date needs to be filled in") if start_from.nil? || start_from.blank? + errors[:base] << "The start date needs to be filled in" if start_from.nil? || start_from.blank? case self.ends_on when 'ends_on_number_of_times' - errors.add_to_base("The number of recurrences needs to be filled in for 'Ends on'") if number_of_occurences.nil? || number_of_occurences.blank? + errors[:base] << "The number of recurrences needs to be filled in for 'Ends on'" if number_of_occurences.nil? || number_of_occurences.blank? when "ends_on_end_date" - errors.add_to_base("The end date needs to be filled in for 'Ends on'") if end_date.nil? || end_date.blank? + errors[:base] << "The end date needs to be filled in for 'Ends on'" if end_date.nil? || end_date.blank? else - errors.add_to_base("The end of the recurrence is not selected") unless ends_on == "no_end_date" + errors[:base] << "The end of the recurrence is not selected" unless ends_on == "no_end_date" end end @@ -112,9 +112,9 @@ class RecurringTodo < ActiveRecord::Base when 'show_from_date' # no validations when 'due_date' - errors.add_to_base("Please select when to show the action") if show_always.nil? + errors[:base] << "Please select when to show the action" if show_always.nil? unless show_always - errors.add_to_base("Please fill in the number of days to show the todo before the due date") if show_from_delta.nil? || show_from_delta.blank? + errors[:base] << "Please fill in the number of days to show the todo before the due date" if show_from_delta.nil? || show_from_delta.blank? end else raise Exception.new, "unexpected value of recurrence target selector '#{self.recurrence_target}'" diff --git a/app/models/todo.rb b/app/models/todo.rb index dc92eb39..5682cb8f 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -372,9 +372,9 @@ class Todo < ActiveRecord::Base context_id = default_context_id unless(context.nil?) - found_context = user.contexts.active.find_by_namepart(context) - found_context = user.contexts.find_by_namepart(context) if found_context.nil? - context_id = found_context.id unless found_context.nil? + found_context = user.contexts.active.where("name like ?", "%#{context}%").first + found_context = user.contexts.where("name like ?", "%#{context}%").first if !found_context + context_id = found_context.id if found_context end unless user.contexts.exists? context_id diff --git a/app/models/user.rb b/app/models/user.rb index 41f8ae4a..0dd35660 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -5,6 +5,11 @@ class User < ActiveRecord::Base # Virtual attribute for the unencrypted password attr_accessor :password attr_protected :is_admin # don't allow mass-assignment for this + + attr_accessible :login, :first_name, :last_name, :password_confirmation, :password, :auth_type, :open_id_url + #for will_paginate plugin + cattr_accessor :per_page + @@per_page = 5 has_many :contexts, :order => 'position ASC', @@ -91,8 +96,6 @@ class User < ActiveRecord::Base has_many :notes, :order => "created_at DESC", :dependent => :delete_all has_one :preference, :dependent => :destroy - attr_protected :is_admin - validates_presence_of :login validates_presence_of :password, :if => :password_required? validates_length_of :password, :within => 5..40, :if => :password_required? @@ -105,10 +108,6 @@ class User < ActiveRecord::Base before_create :crypt_password, :generate_token before_update :crypt_password - #for will_paginate plugin - cattr_accessor :per_page - @@per_page = 5 - def validate_auth_type unless Tracks::Config.auth_schemes.include?(auth_type) errors.add("auth_type", "not a valid authentication type (#{auth_type})") diff --git a/app/views/feedlist/_legend.rhtml b/app/views/feedlist/_legend.html.erb similarity index 100% rename from app/views/feedlist/_legend.rhtml rename to app/views/feedlist/_legend.html.erb diff --git a/app/views/feedlist/index.html.erb b/app/views/feedlist/index.html.erb index 2812f5d6..544282fe 100644 --- a/app/views/feedlist/index.html.erb +++ b/app/views/feedlist/index.html.erb @@ -19,5 +19,5 @@
- <%= render :file => "sidebar/sidebar.html.erb" %> + <%= render :file => "sidebar/sidebar" %>
diff --git a/app/views/feedlist/mobile_index.rhtml b/app/views/feedlist/mobile_index.html.erb similarity index 100% rename from app/views/feedlist/mobile_index.rhtml rename to app/views/feedlist/mobile_index.html.erb diff --git a/app/views/recurring_todos/_recurring_todo_form.erb b/app/views/recurring_todos/_recurring_todo_form.html.erb similarity index 99% rename from app/views/recurring_todos/_recurring_todo_form.erb rename to app/views/recurring_todos/_recurring_todo_form.html.erb index 86fd9730..cdbf9c2a 100644 --- a/app/views/recurring_todos/_recurring_todo_form.erb +++ b/app/views/recurring_todos/_recurring_todo_form.html.erb @@ -1,7 +1,7 @@ <%- reset_tab_index %>
<%= form_for(@new_recurring_todo, :html=> { :id=>'recurring-todo-form-new-action', :name=>'recurring_todo', :class => 'inline-form' }) do -%> -
<%= error_messages_for("item", :object_name => 'action') %>
+
<%= get_list_of_error_messages_for(@new_recurring_todo) %>
diff --git a/app/views/stats/_actions.rhtml b/app/views/stats/_actions.html.erb similarity index 100% rename from app/views/stats/_actions.rhtml rename to app/views/stats/_actions.html.erb diff --git a/app/views/stats/_chart.rhtml b/app/views/stats/_chart.html.erb similarity index 100% rename from app/views/stats/_chart.rhtml rename to app/views/stats/_chart.html.erb diff --git a/app/views/stats/_contexts.rhtml b/app/views/stats/_contexts.html.erb similarity index 100% rename from app/views/stats/_contexts.rhtml rename to app/views/stats/_contexts.html.erb diff --git a/app/views/stats/_projects.rhtml b/app/views/stats/_projects.html.erb similarity index 100% rename from app/views/stats/_projects.rhtml rename to app/views/stats/_projects.html.erb diff --git a/app/views/stats/_tags.rhtml b/app/views/stats/_tags.html.erb similarity index 100% rename from app/views/stats/_tags.rhtml rename to app/views/stats/_tags.html.erb diff --git a/app/views/stats/_totals.rhtml b/app/views/stats/_totals.html.erb similarity index 100% rename from app/views/stats/_totals.rhtml rename to app/views/stats/_totals.html.erb diff --git a/app/views/todos/index.html.erb b/app/views/todos/index.html.erb index b6d7ada7..a7ed7cd0 100644 --- a/app/views/todos/index.html.erb +++ b/app/views/todos/index.html.erb @@ -13,5 +13,5 @@
<%= render :partial => "shared/add_new_item_form" %> - <%= render :file => "sidebar/sidebar.html.erb" %> + <%= render :file => "sidebar/sidebar" %>
\ No newline at end of file diff --git a/app/views/todos/toggle_check.js.erb b/app/views/todos/toggle_check.js.erb index 14bb168d..68adae47 100644 --- a/app/views/todos/toggle_check.js.erb +++ b/app/views/todos/toggle_check.js.erb @@ -184,14 +184,26 @@ function remove_source_container(next_steps) { <% end %> } -function html_for_todo() { - return "<%= @saved && !source_view_is(:done) ? escape_javascript(render(:partial => @todo, :locals => { - :parent_container_type => parent_container_type, - :suppress_project => source_view_is(:project), - :suppress_context => source_view_is(:context) - })) : "" %>"; +function html_for_recurring_todo() { + <%- + js = @saved && @new_recurring_todo ? escape_javascript(render(:partial => @new_recurring_todo, :locals => { :parent_container_type => parent_container_type })) : "" + -%> + return "<%= js %>"; } -function html_for_recurring_todo() { - return "<%= @saved ? escape_javascript(render(:partial => @new_recurring_todo, :locals => { :parent_container_type => parent_container_type })) : "" %>"; +function html_for_todo() { + <%- + js = "" + if @saved && !source_view_is(:done) + js = escape_javascript(render( + :partial => @todo, + :locals => { + :parent_container_type => parent_container_type, + :suppress_project => source_view_is(:project), + :suppress_context => source_view_is(:context) + } + )) + end + -%> + return "<%= js %>"; } \ No newline at end of file diff --git a/app/views/users/change_password.html.erb b/app/views/users/change_password.html.erb index 0f42d4ae..85392028 100644 --- a/app/views/users/change_password.html.erb +++ b/app/views/users/change_password.html.erb @@ -2,7 +2,7 @@

<%= @page_title %>

- <%= error_messages_for 'user' %> + <%= get_list_of_error_messages_for @user %>

<%= t('users.change_password_prompt') %>

diff --git a/config/routes.rb b/config/routes.rb index 630dce2b..7aec1df6 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -51,7 +51,7 @@ Tracksapp::Application.routes.draw do # root :to => 'welcome#index' # See how all your routes lay out with "rake routes" - + # This is a legacy wild controller route that's not recommended for RESTful applications. # Note: This route will make all actions in every controller accessible via GET requests. # match ':controller(/:action(/:id))(.:format)' @@ -64,6 +64,7 @@ Tracksapp::Application.routes.draw do match 'login_cas' => 'users#login_cas' match 'logout' => 'users#logout' match 'calendar' => "todos#calendar" + match 'stats' => 'stats#index' match 'done' => "stats#done", :as => 'done_overview' match 'integrations' => "integrations#index" match 'integrations/rest_api' => "integrations#rest_api", :as => 'rest_api_docs' @@ -113,6 +114,16 @@ Tracksapp::Application.routes.draw do end end match 'todos/tag/:name' => 'todos#tag', :as => :tag + + resources :recurring_todos do + member do + put 'toggle_check' + put 'toggle_star' + end + collection do + get 'done' + end + end resources :users do member do diff --git a/test/fixtures/sample_mms.txt b/test/fixtures/sample_mms.txt index a532e3ab..eb5e7443 100644 --- a/test/fixtures/sample_mms.txt +++ b/test/fixtures/sample_mms.txt @@ -1,6 +1,6 @@ Return-Path: <15555555555/TYPE=PLMN@tmomail.net> Date: Fri, 6 Jun 2008 21:38:26 -0400 -From: 15555555555@tmomail.net +From: 5555555555@tmomail.net To: gtd@tracks.com Message-ID: <3645873.13759311212802713215.JavaMail.mms@rlyatl28> Subject: This is the subject diff --git a/test/functional/feedlist_controller_test.rb b/test/functional/feedlist_controller_test.rb index 372c5048..c490bc8a 100644 --- a/test/functional/feedlist_controller_test.rb +++ b/test/functional/feedlist_controller_test.rb @@ -1,30 +1,17 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require 'feedlist_controller' - -# Re-raise errors caught by the controller. -class FeedlistController; def rescue_action(e) raise e end; end class FeedlistControllerTest < ActionController::TestCase - fixtures :users, :preferences, :projects, :contexts, :todos, :recurring_todos, :notes - - def setup - assert_equal "test", ENV['RAILS_ENV'] - assert_equal "change-me", Tracks::Config.salt - @controller = FeedlistController.new - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new - end def test_get_index_when_not_logged_in get :index - assert_redirected_to :controller => 'login', :action => 'login' + assert_redirected_to login_path end def test_get_index_by_logged_in_user login_as :other_user get :index assert_response :success - assert_equal "TRACKS::Feeds", assigns['page_title'] + assert_equal "TRACKS::Feeds", assigns['page_title'] end -end +end \ No newline at end of file diff --git a/test/functional/message_gateway_test.rb b/test/functional/message_gateway_test.rb index 6e7c3e3e..3c347d79 100644 --- a/test/functional/message_gateway_test.rb +++ b/test/functional/message_gateway_test.rb @@ -1,7 +1,6 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper') class MessageGatewayTest < ActiveSupport::TestCase - fixtures :users, :contexts, :todos def setup @user = users(:sms_user) @@ -14,18 +13,18 @@ class MessageGatewayTest < ActiveSupport::TestCase def test_sms_with_no_subject todo_count = Todo.count - + load_message('sample_sms.txt') # assert some stuff about it being created assert_equal(todo_count+1, Todo.count) - + message_todo = Todo.find(:first, :conditions => {:description => "message_content"}) assert_not_nil(message_todo) - + assert_equal(@inbox, message_todo.context) assert_equal(@user, message_todo.user) end - + def test_double_sms todo_count = Todo.count load_message('sample_sms.txt') @@ -56,18 +55,18 @@ class MessageGatewayTest < ActiveSupport::TestCase MessageGateway.receive(badmessage) assert_equal(todo_count, Todo.count) end - + def test_direct_to_context message = File.read(File.join(Rails.root, 'test', 'fixtures', 'sample_sms.txt')) - + valid_context_msg = message.gsub('message_content', 'this is a task @ anothercontext') invalid_context_msg = message.gsub('message_content', 'this is also a task @ notacontext') - + MessageGateway.receive(valid_context_msg) valid_context_todo = Todo.find(:first, :conditions => {:description => "this is a task"}) assert_not_nil(valid_context_todo) assert_equal(contexts(:anothercontext), valid_context_todo.context) - + MessageGateway.receive(invalid_context_msg) invalid_context_todo = Todo.find(:first, :conditions => {:description => 'this is also a task'}) assert_not_nil(invalid_context_todo) diff --git a/test/functional/preferences_controller_test.rb b/test/functional/preferences_controller_test.rb index b8de7a95..bc0913f4 100644 --- a/test/functional/preferences_controller_test.rb +++ b/test/functional/preferences_controller_test.rb @@ -1,9 +1,9 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper') class PreferencesControllerTest < ActionController::TestCase - fixtures :users, :preferences def setup + super assert_equal "test", Rails.env assert_equal "change-me", Tracks::Config.salt end diff --git a/test/functional/recurring_todos_controller_test.rb b/test/functional/recurring_todos_controller_test.rb index bdfeef65..8cdabcee 100644 --- a/test/functional/recurring_todos_controller_test.rb +++ b/test/functional/recurring_todos_controller_test.rb @@ -1,16 +1,10 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper') class RecurringTodosControllerTest < ActionController::TestCase - fixtures :users, :preferences, :projects, :contexts, :todos, :tags, :taggings, :recurring_todos - - def setup - @controller = RecurringTodosController.new - @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new - end def test_get_index_when_not_logged_in get :index - assert_redirected_to :controller => 'login', :action => 'login' + assert_redirected_to login_path end def test_destroy_recurring_todo diff --git a/test/functional/stats_controller_test.rb b/test/functional/stats_controller_test.rb index 0c965f90..47515637 100644 --- a/test/functional/stats_controller_test.rb +++ b/test/functional/stats_controller_test.rb @@ -1,21 +1,10 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require 'stats_controller' - -# Re-raise errors caught by the controller. -class StatsController; def rescue_action(e) raise e end; end class StatsControllerTest < ActionController::TestCase - fixtures :users, :preferences, :projects, :contexts, :todos, :recurring_todos, :recurring_todos, :tags, :taggings - - def setup - @controller = StatsController.new - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new - end def test_get_index_when_not_logged_in get :index - assert_redirected_to :controller => 'login', :action => 'login' + assert_redirected_to login_url end def test_get_index diff --git a/test/functional/todo_container_controller_test_base.rb b/test/functional/todo_container_controller_test_base.rb deleted file mode 100644 index ce810195..00000000 --- a/test/functional/todo_container_controller_test_base.rb +++ /dev/null @@ -1,21 +0,0 @@ -class TodoContainerControllerTestBase < ActionController::TestCase - - def setup_controller_request_and_response - # ## override with empty - # TODO: remove these ugly hacks - end - - def perform_setup(container_class, controller_class) - @controller = controller_class.new - @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new - login_as :other_user - @initial_count = container_class.count - @container_class = container_class - end - - def test_truth - assert true - end - - -end diff --git a/test/functional/todos_controller_test.rb b/test/functional/todos_controller_test.rb index cfb9cdec..861e8c97 100644 --- a/test/functional/todos_controller_test.rb +++ b/test/functional/todos_controller_test.rb @@ -1,20 +1,14 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require 'todos_controller' - -# Re-raise errors caught by the controller. -class TodosController; def rescue_action(e) raise e end; end class TodosControllerTest < ActionController::TestCase fixtures :users, :preferences, :projects, :contexts, :todos, :tags, :taggings, :recurring_todos def setup - @controller = TodosController.new - @request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new end def test_get_index_when_not_logged_in get :index - assert_redirected_to :controller => 'login', :action => 'login' + assert_redirected_to login_url end def test_not_done_counts @@ -32,7 +26,7 @@ class TodosControllerTest < ActionController::TestCase assert_equal 3, assigns['context_not_done_counts'][contexts(:call).id] assert_equal 1, assigns['context_not_done_counts'][contexts(:lab).id] end - + def test_cached_not_done_counts_after_hiding_project p = Project.find(1) p.hide! @@ -43,7 +37,7 @@ class TodosControllerTest < ActionController::TestCase assert_equal 2, assigns['context_not_done_counts'][contexts(:call).id] assert_equal nil, assigns['context_not_done_counts'][contexts(:lab).id] end - + def test_tag_is_retrieved_properly login_as(:admin_user) get :index @@ -52,7 +46,7 @@ class TodosControllerTest < ActionController::TestCase assert_equal 'foo', t.tags[0].name assert !t.starred? end - + def test_tagging_changes_to_tag_with_numbers # by default has_many_polymorph searches for tags with given id if the tag is a number. we do not want that login_as(:admin_user) @@ -66,7 +60,7 @@ class TodosControllerTest < ActionController::TestCase assert_equal t.description, "test tags" assert_equal 3, t.tags.count end - + def test_tagging_changes_to_handle_empty_tags # by default has_many_polymorph searches for tags with given id if the tag is a number. we do not want that login_as(:admin_user) @@ -80,7 +74,7 @@ class TodosControllerTest < ActionController::TestCase assert_equal t.description, "test tags" assert_equal 2, t.tags.count end - + def test_not_done_counts_after_hiding_project p = Project.find(1) p.hide! @@ -91,7 +85,7 @@ class TodosControllerTest < ActionController::TestCase assert_equal 2, contexts(:call).todos.active.count assert_equal 0, contexts(:lab).todos.active.count end - + def test_not_done_counts_after_hiding_and_unhiding_project p = Project.find(1) p.hide! @@ -104,7 +98,7 @@ class TodosControllerTest < ActionController::TestCase assert_equal 3, contexts(:call).todos.not_completed.count assert_equal 1, contexts(:lab).todos.not_completed.count end - + def test_deferred_count_for_project_source_view login_as(:admin_user) xhr :post, :toggle_check, :id => 5, :_source_view => 'project' @@ -112,21 +106,21 @@ class TodosControllerTest < ActionController::TestCase xhr :post, :toggle_check, :id => 15, :_source_view => 'project' assert_equal 0, assigns['remaining_deferred_or_pending_count'] end - + def test_destroy_todo login_as(:admin_user) xhr :post, :destroy, :id => 1, :_source_view => 'todo' todo = Todo.find_by_id(1) assert_nil todo end - + def test_create_todo assert_difference 'Todo.count' do login_as(:admin_user) put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{"notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"foo bar" end end - + def test_create_todo_via_xml login_as(:admin_user) assert_difference 'Todo.count' do @@ -134,10 +128,10 @@ class TodosControllerTest < ActionController::TestCase assert_response 201 end end - + def test_fail_to_create_todo_via_xml login_as(:admin_user) - # #try to create with no context, which is not valid + # try to create with no context, which is not valid put :create, :format => "xml", "request" => { "project_name"=>"Build a working time machine", "todo"=>{"notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"foo bar" } @@ -146,687 +140,687 @@ class TodosControllerTest < ActionController::TestCase assert_xml_select "error", "Context can't be blank" end end - - def test_create_deferred_todo - original_todo_count = Todo.count - login_as(:admin_user) - put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{"notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2026", 'show_from' => '30/10/2026'}, "tag_list"=>"foo bar" - assert_equal original_todo_count + 1, Todo.count - end - - def test_update_todo_project - t = Todo.find(1) - login_as(:admin_user) - xhr :post, :update, :id => 1, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{"id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"foo bar" - t = Todo.find(1) - assert_equal 1, t.project_id - end - - def test_update_todo_project_to_none - t = Todo.find(1) - login_as(:admin_user) - xhr :post, :update, :id => 1, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"None", "todo"=>{"id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"foo bar" - t = Todo.find(1) - assert_nil t.project_id - end - - def test_update_todo_to_deferred_is_reflected_in_badge_count - login_as(:admin_user) - get :index - assert_equal 11, assigns['count'] - xhr :post, :update, :id => 1, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Make more money than Billy Gates", "todo"=>{"id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006", "show_from"=>"30/11/2030"}, "tag_list"=>"foo bar" - assert_equal 10, assigns['down_count'] - end - - def test_update_todo - t = Todo.find(1) - login_as(:admin_user) - xhr :post, :update, :id => 1, :_source_view => 'todo', "todo"=>{"context_id"=>"1", "project_id"=>"2", "id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"foo, bar" - t = Todo.find(1) - assert_equal "Call Warren Buffet to find out how much he makes per day", t.description - assert_equal "bar, foo", t.tag_list - expected = Date.new(2006,11,30) - actual = t.due.to_date - assert_equal expected, actual, "Expected #{expected.to_s(:db)}, was #{actual.to_s(:db)}" - end - - def test_update_todos_with_blank_project_name - t = Todo.find(1) - login_as(:admin_user) - xhr :post, :update, :id => 1, :_source_view => 'todo', :project_name => '', "todo"=>{"id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"foo, bar" - t.reload - assert t.project.nil? - end - - def test_update_todo_tags_to_none - t = Todo.find(1) - login_as(:admin_user) - xhr :post, :update, :id => 1, :_source_view => 'todo', "todo"=>{"context_id"=>"1", "project_id"=>"2", "id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"" - t = Todo.find(1) - assert_equal true, t.tag_list.empty? - end - - def test_update_todo_tags_with_whitespace_and_dots - t = Todo.find(1) - login_as(:admin_user) - taglist = " one , two,three ,four, 8.1.2, version1.5" - xhr :post, :update, :id => 1, :_source_view => 'todo', "todo"=>{"context_id"=>"1", "project_id"=>"2", "id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>taglist - t = Todo.find(1) - assert_equal "8.1.2, four, one, three, two, version1.5", t.tag_list - end - - def test_add_multiple_todos - login_as(:admin_user) - - start_count = Todo.count - put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{ - :multiple_todos=>"a\nb\nmuch \"ado\" about \'nothing\'"} - - assert_equal start_count+3, Todo.count, "two todos should have been added" - end - - def test_add_multiple_todos_with_validation_error - login_as(:admin_user) - - long_string = "a" * 500 - - start_count = Todo.count - put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{ - :multiple_todos=>"a\nb\nmuch \"ado\" about \'nothing\'\n#{long_string}"} - - assert_equal start_count, Todo.count, "no todos should have been added" - end - - def test_add_multiple_dependent_todos - login_as(:admin_user) - - start_count = Todo.count - put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{ - :multiple_todos=>"a\nb"}, :todos_sequential => 'true' - put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{ - :multiple_todos=>"c\nd"}, :todos_sequential => 'false' - - assert_equal start_count+4, Todo.count, "four todos should have been added" - - # find a,b,c and d - %w{a b c d}.each do |todo| - eval "@#{todo} = Todo.find_by_description('#{todo}')" - eval "assert !@#{todo}.nil?, 'a todo with description \"#{todo}\" should just have been added'" - end - - assert @b.predecessors.include?(@a), "a should be a predeccesor of b" - assert !@d.predecessors.include?(@c), "c should not be a predecessor of d" - end - - def test_find_tagged_with - login_as(:admin_user) - @user = User.find(@request.session['user_id']) - tag = Tag.find_by_name('foo').taggings - @tagged = tag.count - get :tag, :name => 'foo' - assert_response :success - assert_equal 3, @tagged - end - - def test_rss_feed - login_as(:admin_user) - get :index, { :format => "rss" } - assert_equal 'application/rss+xml', @response.content_type - # puts @response.body - - assert_xml_select 'rss[version="2.0"]' do - assert_select 'channel' do - assert_select '>title', 'Actions' - assert_select '>description', "Actions for #{users(:admin_user).display_name}" - assert_select 'language', 'en-us' - assert_select 'ttl', '40' - assert_select 'item', 11 do - assert_select 'title', /.+/ - assert_select 'description', /.*/ - assert_select 'link', %r{http://test.host/contexts/.+} - assert_select 'guid', %r{http://test.host/todos/.+} - assert_select 'pubDate', todos(:book).updated_at.to_s(:rfc822) - end - end - end - end - - def test_rss_feed_with_limit - login_as(:admin_user) - get :index, { :format => "rss", :limit => '5' } - - assert_xml_select 'rss[version="2.0"]' do - assert_select 'channel' do - assert_select '>title', 'Actions' - assert_select '>description', "Actions for #{users(:admin_user).display_name}" - assert_select 'item', 5 do - assert_select 'title', /.+/ - assert_select 'description', /.*/ - end - end - end - end - - def test_rss_feed_not_accessible_to_anonymous_user_without_token - login_as nil - get :index, { :format => "rss" } - assert_response 401 - end - - def test_rss_feed_not_accessible_to_anonymous_user_with_invalid_token - login_as nil - get :index, { :format => "rss", :token => 'foo' } - assert_response 401 - end - - def test_rss_feed_accessible_to_anonymous_user_with_valid_token - login_as nil - get :index, { :format => "rss", :token => users(:admin_user).token } - assert_response :ok - end - - def test_atom_feed_content - login_as :admin_user - get :index, { :format => "atom" } - assert_equal 'application/atom+xml', @response.content_type - # #puts @response.body - - assert_xml_select 'feed[xmlns="http://www.w3.org/2005/Atom"]' do - assert_xml_select '>title', 'Actions' - assert_xml_select '>subtitle', "Actions for #{users(:admin_user).display_name}" - assert_xml_select 'entry', 11 do - assert_xml_select 'title', /.+/ - assert_xml_select 'content[type="html"]', /.*/ - assert_xml_select 'published', /(#{Regexp.escape(todos(:book).updated_at.xmlschema)}|#{Regexp.escape(projects(:moremoney).updated_at.xmlschema)})/ - end - end - end - - def test_atom_feed_not_accessible_to_anonymous_user_without_token - login_as nil - get :index, { :format => "atom" } - assert_response 401 - end - - def test_atom_feed_not_accessible_to_anonymous_user_with_invalid_token - login_as nil - get :index, { :format => "atom", :token => 'foo' } - assert_response 401 - end - - def test_atom_feed_accessible_to_anonymous_user_with_valid_token - login_as nil - get :index, { :format => "atom", :token => users(:admin_user).token } - assert_response :ok - end - - def test_text_feed_content - login_as(:admin_user) - get :index, { :format => "txt" } - assert_equal 'text/plain', @response.content_type - assert !(/ /.match(@response.body)) - # #puts @response.body - end - - def test_text_feed_not_accessible_to_anonymous_user_without_token - login_as nil - get :index, { :format => "txt" } - assert_response 401 - end - - def test_text_feed_not_accessible_to_anonymous_user_with_invalid_token - login_as nil - get :index, { :format => "txt", :token => 'foo' } - assert_response 401 - end - - def test_text_feed_accessible_to_anonymous_user_with_valid_token - login_as nil - get :index, { :format => "txt", :token => users(:admin_user).token } - assert_response :ok - end - - def test_ical_feed_content - login_as :admin_user - get :index, { :format => "ics" } - assert_equal 'text/calendar', @response.content_type - assert !(/ /.match(@response.body)) - # #puts @response.body - end - - def test_mobile_index_uses_text_html_content_type - login_as(:admin_user) - get :index, { :format => "m" } - assert_equal 'text/html', @response.content_type - end - - def test_mobile_index_assigns_down_count - login_as(:admin_user) - get :index, { :format => "m" } - assert_equal 11, assigns['down_count'] - end - - def test_mobile_create_action_creates_a_new_todo - login_as(:admin_user) - post :create, {"format"=>"m", "todo"=>{"context_id"=>"2", - "due(1i)"=>"2007", "due(2i)"=>"1", "due(3i)"=>"2", - "show_from(1i)"=>"", "show_from(2i)"=>"", "show_from(3i)"=>"", - "project_id"=>"1", - "notes"=>"test notes", "description"=>"test_mobile_create_action"}} - t = Todo.find_by_description("test_mobile_create_action") - assert_not_nil t - assert_equal 2, t.context_id - assert_equal 1, t.project_id - assert t.active? - assert_equal 'test notes', t.notes - assert_nil t.show_from - assert_equal Date.new(2007,1,2), t.due.to_date - end - - def test_mobile_create_action_redirects_to_mobile_home_page_when_successful - login_as(:admin_user) - post :create, {"format"=>"m", "todo"=>{"context_id"=>"2", - "due(1i)"=>"2007", "due(2i)"=>"1", "due(3i)"=>"2", - "show_from(1i)"=>"", "show_from(2i)"=>"", "show_from(3i)"=>"", - "project_id"=>"1", - "notes"=>"test notes", "description"=>"test_mobile_create_action", "state"=>"0"}} - assert_redirected_to '/mobile' - end - - def test_mobile_create_action_renders_new_template_when_save_fails - login_as(:admin_user) - post :create, {"format"=>"m", "todo"=>{"context_id"=>"2", - "due(1i)"=>"2007", "due(2i)"=>"1", "due(3i)"=>"2", - "show_from(1i)"=>"", "show_from(2i)"=>"", "show_from(3i)"=>"", - "project_id"=>"1", - "notes"=>"test notes"}, "tag_list"=>"test, test2"} - assert_template 'todos/new' - end - - def test_toggle_check_on_recurring_todo - login_as(:admin_user) - - # link todo_1 and recurring_todo_1 - recurring_todo_1 = RecurringTodo.find(1) - todo_1 = Todo.find_by_recurring_todo_id(1) - - # mark todo_1 as complete by toggle_check - xhr :post, :toggle_check, :id => todo_1.id, :_source_view => 'todo' - todo_1.reload - assert todo_1.completed? - - # check that there is only one active todo belonging to recurring_todo - count = Todo.count(:all, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'active'}) - assert_equal 1, count - - # check there is a new todo linked to the recurring pattern - next_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'active'}) - assert_equal "Call Bill Gates every day", next_todo.description - # check that the new todo is not the same as todo_1 - assert_not_equal todo_1.id, next_todo.id - - # change recurrence pattern to monthly and set show_from 2 days before due - # date this forces the next todo to be put in the tickler - recurring_todo_1.show_from_delta = 2 - recurring_todo_1.show_always = 0 - recurring_todo_1.target = 'due_date' - recurring_todo_1.recurring_period = 'monthly' - recurring_todo_1.recurrence_selector = 0 - recurring_todo_1.every_other1 = 1 - recurring_todo_1.every_other2 = 2 - recurring_todo_1.every_other3 = 5 - # use assert to catch validation errors if present. we need to replace - # this with a good factory implementation - assert recurring_todo_1.save - - # mark next_todo as complete by toggle_check - xhr :post, :toggle_check, :id => next_todo.id, :_source_view => 'todo' - next_todo.reload - assert next_todo.completed? - - # check that there are three todos belonging to recurring_todo: two - # completed and one deferred - count = Todo.count(:all, :conditions => {:recurring_todo_id => recurring_todo_1.id}) - assert_equal 3, count - - # check there is a new todo linked to the recurring pattern in the tickler - next_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'deferred'}) - assert !next_todo.nil? - assert_equal "Call Bill Gates every day", next_todo.description - # check that the todo is in the tickler - assert !next_todo.show_from.nil? - end - - def test_toggle_check_on_rec_todo_show_from_today - login_as(:admin_user) - - # link todo_1 and recurring_todo_1 - recurring_todo_1 = RecurringTodo.find(1) - set_user_to_current_time_zone(recurring_todo_1.user) - todo_1 = Todo.find_by_recurring_todo_id(1) - today = Time.zone.now.at_midnight - - # change recurrence pattern to monthly and set show_from to today - recurring_todo_1.target = 'show_from_date' - recurring_todo_1.recurring_period = 'monthly' - recurring_todo_1.recurrence_selector = 0 - recurring_todo_1.every_other1 = today.day - recurring_todo_1.every_other2 = 1 - assert recurring_todo_1.save - - # mark todo_1 as complete by toggle_check, this gets rid of todo_1 that was - # not correctly created from the adjusted recurring pattern we defined - # above. - xhr :post, :toggle_check, :id => todo_1.id, :_source_view => 'todo' - todo_1.reload - assert todo_1.completed? - - # locate the new todo. This todo is created from the adjusted recurring - # pattern defined in this test - new_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'active'}) - assert !new_todo.nil? - - # mark new_todo as complete by toggle_check - xhr :post, :toggle_check, :id => new_todo.id, :_source_view => 'todo' - new_todo.reload - assert todo_1.completed? - - # locate the new todo in tickler - new_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'deferred'}) - assert !new_todo.nil? - - assert_equal "Call Bill Gates every day", new_todo.description - # check that the new todo is not the same as todo_1 - assert_not_equal todo_1.id, new_todo.id - - # check that the new_todo is in the tickler to show next month - assert !new_todo.show_from.nil? - - # do not use today here. It somehow gets messed up with the timezone calculation. - next_month = (Time.zone.now + 1.month).at_midnight - - assert_equal next_month.utc.to_date.to_s(:db), new_todo.show_from.utc.to_date.to_s(:db) - end - - def test_check_for_next_todo - login_as :admin_user - - recurring_todo_1 = RecurringTodo.find(5) - @todo = Todo.find_by_recurring_todo_id(1) - assert @todo.from_recurring_todo? - # rewire @todo to yearly recurring todo - @todo.recurring_todo_id = 5 - - # make todo due tomorrow and change recurring date also to tomorrow - @todo.due = Time.zone.now + 1.day - @todo.save - recurring_todo_1.every_other1 = @todo.due.day - recurring_todo_1.every_other2 = @todo.due.month - recurring_todo_1.save - - # mark todo complete - xhr :post, :toggle_check, :id => @todo.id, :_source_view => 'todo' - @todo.reload - assert @todo.completed? - - # check that there is no active todo - next_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'active'}) - assert next_todo.nil? - - # check for new deferred todo - next_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'deferred'}) - assert !next_todo.nil? - # check that the due date of the new todo is later than tomorrow - assert next_todo.due > @todo.due - end - - def test_removing_hidden_project_activates_todo - login_as(:admin_user) - - # get a project and hide it, todos in the project should be hidden - p = projects(:timemachine) - p.hide! - assert p.reload().hidden? - todo = p.todos.first - assert_equal "project_hidden", todo.state - - # clear project from todo: the todo should be unhidden - xhr :post, :update, :id => 5, :_source_view => 'todo', "project_name"=>"None", "todo"=>{} - todo.reload() - assert_equal "active", todo.state - end - - def test_url_with_slash_in_query_string_are_parsed_correctly - # See http://blog.swivel.com/code/2009/06/rails-auto_link-and-certain-query-strings.html - login_as(:admin_user) - user = users(:admin_user) - todo = user.todos.first - url = "http://example.com/foo?bar=/baz" - todo.notes = "foo #{url} bar" - todo.save! - get :index - assert_select("a[href=#{url}]") - end - - def test_format_note_normal - login_as(:admin_user) - todo = users(:admin_user).todos.first - todo.notes = "A normal description." - todo.save! - get :index - assert_select("div#notes_todo_#{todo.id}", "A normal description.") - end - - def test_format_note_markdown - login_as(:admin_user) - todo = users(:admin_user).todos.first - todo.notes = "A *bold description*." - todo.save! - get :index - assert_select("div#notes_todo_#{todo.id}", "A bold description.") - assert_select("div#notes_todo_#{todo.id} strong", "bold description") - end - - def test_format_note_link - login_as(:admin_user) - todo = users(:admin_user).todos.first - todo.notes = "A link to http://github.com/." - todo.save! - get :index - assert_select("div#notes_todo_#{todo.id}", 'A link to http://github.com/.') - assert_select("div#notes_todo_#{todo.id} a[href=http://github.com/]", 'http://github.com/') - end - - def test_format_note_link_message - login_as(:admin_user) - todo = users(:admin_user).todos.first - todo.raw_notes = "A Mail.app message:// link" - todo.save! - get :index - assert_select("div#notes_todo_#{todo.id}", 'A Mail.app message://<ABCDEF-GHADB-123455-FOO-BAR@example.com> link') - assert_select("div#notes_todo_#{todo.id} a", 'message://<ABCDEF-GHADB-123455-FOO-BAR@example.com>') - assert_select("div#notes_todo_#{todo.id} a[href=message://<ABCDEF-GHADB-123455-FOO-BAR@example.com>]", 'message://<ABCDEF-GHADB-123455-FOO-BAR@example.com>') - end - - def test_format_note_link_onenote - login_as(:admin_user) - todo = users(:admin_user).todos.first - todo.notes = ' "link me to onenote":onenote:///E:\OneNote\dir\notes.one#PAGE§ion-id={FD597D3A-3793-495F-8345-23D34A00DD3B}&page-id={1C95A1C7-6408-4804-B3B5-96C28426022B}&end' - todo.save! - get :index - assert_select("div#notes_todo_#{todo.id}", 'link me to onenote') - assert_select("div#notes_todo_#{todo.id} a", 'link me to onenote') - assert_select("div#notes_todo_#{todo.id} a[href=onenote:///E:\\OneNote\\dir\\notes.one#PAGE&section-id={FD597D3A-3793-495F-8345-23D34A00DD3B}&page-id={1C95A1C7-6408-4804-B3B5-96C28426022B}&end]", 'link me to onenote') - end - - def test_get_boolean_expression_from_parameters_of_tag_view_single_tag - login_as(:admin_user) - get :tag, :name => "single" - assert_equal true, assigns['single_tag'], "should recognize it is a single tag name" - assert_equal "single", assigns['tag_expr'][0][0], "should store the single tag" - assert_equal "single", assigns['tag_name'], "should store the single tag name" - end - - def test_get_boolean_expression_from_parameters_of_tag_view_multiple_tags - login_as(:admin_user) - get :tag, :name => "multiple", :and => "tags", :and1 => "present", :and2 => "here" - assert_equal false, assigns['single_tag'], "should recognize it has multiple tags" - assert_equal 4, assigns['tag_expr'].size, "should have 4 AND expressions" - end - - def test_get_boolean_expression_from_parameters_of_tag_view_multiple_tags_without_digitless_and - login_as(:admin_user) - get :tag, :name => "multiple", :and1 => "tags", :and2 => "present", :and3 => "here" - assert_equal false, assigns['single_tag'], "should recognize it has multiple tags" - assert_equal 4, assigns['tag_expr'].size, "should have 4 AND expressions" - end - - def test_get_boolean_expression_from_parameters_of_tag_view_multiple_ORs - login_as(:admin_user) - get :tag, :name => "multiple,tags,present" - assert_equal false, assigns['single_tag'], "should recognize it has multiple tags" - assert_equal 1, assigns['tag_expr'].size, "should have 1 expressions" - assert_equal 3, assigns['tag_expr'][0].size, "should have 3 ORs in 1st expression" - end - - def test_get_boolean_expression_from_parameters_of_tag_view_multiple_ORs_and_ANDS - login_as(:admin_user) - get :tag, :name => "multiple,tags,present", :and => "here,is,two", :and1=>"and,three" - assert_equal false, assigns['single_tag'], "should recognize it has multiple tags" - assert_equal 3, assigns['tag_expr'].size, "should have 3 expressions" - assert_equal 3, assigns['tag_expr'][0].size, "should have 3 ORs in 1st expression" - assert_equal 3, assigns['tag_expr'][1].size, "should have 3 ORs in 2nd expression" - assert_equal 2, assigns['tag_expr'][2].size, "should have 2 ORs in 3rd expression" - end - - def test_set_right_title - login_as(:admin_user) - - get :tag, :name => "foo" - assert_equal "foo", assigns['tag_title'] - get :tag, :name => "foo,bar", :and => "baz" - assert_equal "foo,bar AND baz", assigns['tag_title'] - end - - def test_set_default_tag - login_as(:admin_user) - - get :tag, :name => "foo" - assert_equal "foo", assigns['initial_tags'] - get :tag, :name => "foo,bar", :and => "baz" - assert_equal "foo", assigns['initial_tags'] - end - - def test_tag_text_feed_not_accessible_to_anonymous_user_without_token - login_as nil - get :tag, {:name => "foo", :format => "txt" } - assert_response 401 - end - - def test_make_todo_dependent - login_as(:admin_user) - - predecessor = todos(:call_bill) - successor = todos(:call_dino_ext) - - # no predecessors yet - assert_equal 0, successor.predecessors.size - - # add predecessor - put :add_predecessor, :predecessor=>predecessor.id, :successor=>successor.id - - assert_equal 1, successor.predecessors.count - assert_equal predecessor.id, successor.predecessors.first.id - end - - def test_make_todo_with_dependencies_dependent - login_as(:admin_user) - - predecessor = todos(:call_bill) - successor = todos(:call_dino_ext) - other_todo = todos(:phone_grandfather) - - # predecessor -> successor - put :add_predecessor, :predecessor=>predecessor.id, :successor=>successor.id - - # other_todo -> predecessor -> successor - put :add_predecessor, :predecessor=>other_todo.id, :successor=>predecessor.id - - assert_equal 1, successor.predecessors(true).count - assert_equal 0, other_todo.predecessors(true).count - assert_equal 1, predecessor.predecessors(true).count - assert_equal predecessor.id, successor.predecessors.first.id - assert_equal other_todo.id, predecessor.predecessors.first.id - end - - def test_mingle_dependent_todos_leave - # based on #1271 - login_as(:admin_user) - - t1 = todos(:call_bill) - t2 = todos(:call_dino_ext) - t3 = todos(:phone_grandfather) - t4 = todos(:construct_dilation_device) - - # t1 -> t2 - put :add_predecessor, :predecessor=>t1.id, :successor=>t2.id - # t3 -> t4 - put :add_predecessor, :predecessor=>t3.id, :successor=>t4.id - - # t2 -> t4 - put :add_predecessor, :predecessor=>t2.id, :successor=>t4.id - - # should be: t1 -> t2 -> t4 and t3 -> t4 - assert t4.predecessors.map(&:id).include?(t2.id) - assert t4.predecessors.map(&:id).include?(t3.id) - assert t2.predecessors.map(&:id).include?(t1.id) - end - - def test_mingle_dependent_todos_root - # based on #1271 - login_as(:admin_user) - - t1 = todos(:call_bill) - t2 = todos(:call_dino_ext) - t3 = todos(:phone_grandfather) - t4 = todos(:construct_dilation_device) - - # t1 -> t2 - put :add_predecessor, :predecessor=>t1.id, :successor=>t2.id - # t3 -> t4 - put :add_predecessor, :predecessor=>t3.id, :successor=>t4.id - - # t3 -> t2 - put :add_predecessor, :predecessor=>t3.id, :successor=>t2.id - - # should be: t1 -> t2 and t3 -> t4 & t2 - assert t3.successors.map(&:id).include?(t4.id) - assert t3.successors.map(&:id).include?(t2.id) - assert t2.predecessors.map(&:id).include?(t1.id) - assert t2.predecessors.map(&:id).include?(t3.id) - end - - def test_unmingle_dependent_todos - # based on #1271 - login_as(:admin_user) - - t1 = todos(:call_bill) - t2 = todos(:call_dino_ext) - t3 = todos(:phone_grandfather) - t4 = todos(:construct_dilation_device) - - # create same dependency tree as previous test - # should be: t1 -> t2 -> t4 and t3 -> t4 - put :add_predecessor, :predecessor=>t1.id, :successor=>t2.id - put :add_predecessor, :predecessor=>t3.id, :successor=>t4.id - put :add_predecessor, :predecessor=>t2.id, :successor=>t4.id - - # removing t4 as successor of t2 should leave t4 blocked with t3 as predecessor - put :remove_predecessor, :predecessor=>t2.id, :id=>t4.id - - t4.reload - assert t4.pending?, "t4 should remain pending" - assert t4.predecessors.map(&:id).include?(t3.id) - end + # + # def test_create_deferred_todo + # original_todo_count = Todo.count + # login_as(:admin_user) + # put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{"notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2026", 'show_from' => '30/10/2026'}, "tag_list"=>"foo bar" + # assert_equal original_todo_count + 1, Todo.count + # end + # + # def test_update_todo_project + # t = Todo.find(1) + # login_as(:admin_user) + # xhr :post, :update, :id => 1, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{"id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"foo bar" + # t = Todo.find(1) + # assert_equal 1, t.project_id + # end + # + # def test_update_todo_project_to_none + # t = Todo.find(1) + # login_as(:admin_user) + # xhr :post, :update, :id => 1, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"None", "todo"=>{"id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"foo bar" + # t = Todo.find(1) + # assert_nil t.project_id + # end + # + # def test_update_todo_to_deferred_is_reflected_in_badge_count + # login_as(:admin_user) + # get :index + # assert_equal 11, assigns['count'] + # xhr :post, :update, :id => 1, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Make more money than Billy Gates", "todo"=>{"id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006", "show_from"=>"30/11/2030"}, "tag_list"=>"foo bar" + # assert_equal 10, assigns['down_count'] + # end + # + # def test_update_todo + # t = Todo.find(1) + # login_as(:admin_user) + # xhr :post, :update, :id => 1, :_source_view => 'todo', "todo"=>{"context_id"=>"1", "project_id"=>"2", "id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"foo, bar" + # t = Todo.find(1) + # assert_equal "Call Warren Buffet to find out how much he makes per day", t.description + # assert_equal "bar, foo", t.tag_list + # expected = Date.new(2006,11,30) + # actual = t.due.to_date + # assert_equal expected, actual, "Expected #{expected.to_s(:db)}, was #{actual.to_s(:db)}" + # end + # + # def test_update_todos_with_blank_project_name + # t = Todo.find(1) + # login_as(:admin_user) + # xhr :post, :update, :id => 1, :_source_view => 'todo', :project_name => '', "todo"=>{"id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"foo, bar" + # t.reload + # assert t.project.nil? + # end + # + # def test_update_todo_tags_to_none + # t = Todo.find(1) + # login_as(:admin_user) + # xhr :post, :update, :id => 1, :_source_view => 'todo', "todo"=>{"context_id"=>"1", "project_id"=>"2", "id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>"" + # t = Todo.find(1) + # assert_equal true, t.tag_list.empty? + # end + # + # def test_update_todo_tags_with_whitespace_and_dots + # t = Todo.find(1) + # login_as(:admin_user) + # taglist = " one , two,three ,four, 8.1.2, version1.5" + # xhr :post, :update, :id => 1, :_source_view => 'todo', "todo"=>{"context_id"=>"1", "project_id"=>"2", "id"=>"1", "notes"=>"", "description"=>"Call Warren Buffet to find out how much he makes per day", "due"=>"30/11/2006"}, "tag_list"=>taglist + # t = Todo.find(1) + # assert_equal "8.1.2, four, one, three, two, version1.5", t.tag_list + # end + # + # def test_add_multiple_todos + # login_as(:admin_user) + # + # start_count = Todo.count + # put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{ + # :multiple_todos=>"a\nb\nmuch \"ado\" about \'nothing\'"} + # + # assert_equal start_count+3, Todo.count, "two todos should have been added" + # end + # + # def test_add_multiple_todos_with_validation_error + # login_as(:admin_user) + # + # long_string = "a" * 500 + # + # start_count = Todo.count + # put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{ + # :multiple_todos=>"a\nb\nmuch \"ado\" about \'nothing\'\n#{long_string}"} + # + # assert_equal start_count, Todo.count, "no todos should have been added" + # end + # + # def test_add_multiple_dependent_todos + # login_as(:admin_user) + # + # start_count = Todo.count + # put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{ + # :multiple_todos=>"a\nb"}, :todos_sequential => 'true' + # put :create, :_source_view => 'todo', "context_name"=>"library", "project_name"=>"Build a working time machine", "todo"=>{ + # :multiple_todos=>"c\nd"}, :todos_sequential => 'false' + # + # assert_equal start_count+4, Todo.count, "four todos should have been added" + # + # # find a,b,c and d + # %w{a b c d}.each do |todo| + # eval "@#{todo} = Todo.find_by_description('#{todo}')" + # eval "assert !@#{todo}.nil?, 'a todo with description \"#{todo}\" should just have been added'" + # end + # + # assert @b.predecessors.include?(@a), "a should be a predeccesor of b" + # assert !@d.predecessors.include?(@c), "c should not be a predecessor of d" + # end + # + # def test_find_tagged_with + # login_as(:admin_user) + # @user = User.find(@request.session['user_id']) + # tag = Tag.find_by_name('foo').taggings + # @tagged = tag.count + # get :tag, :name => 'foo' + # assert_response :success + # assert_equal 3, @tagged + # end + # + # def test_rss_feed + # login_as(:admin_user) + # get :index, { :format => "rss" } + # assert_equal 'application/rss+xml', @response.content_type + # # puts @response.body + # + # assert_xml_select 'rss[version="2.0"]' do + # assert_select 'channel' do + # assert_select '>title', 'Actions' + # assert_select '>description', "Actions for #{users(:admin_user).display_name}" + # assert_select 'language', 'en-us' + # assert_select 'ttl', '40' + # assert_select 'item', 11 do + # assert_select 'title', /.+/ + # assert_select 'description', /.*/ + # assert_select 'link', %r{http://test.host/contexts/.+} + # assert_select 'guid', %r{http://test.host/todos/.+} + # assert_select 'pubDate', todos(:book).updated_at.to_s(:rfc822) + # end + # end + # end + # end + # + # def test_rss_feed_with_limit + # login_as(:admin_user) + # get :index, { :format => "rss", :limit => '5' } + # + # assert_xml_select 'rss[version="2.0"]' do + # assert_select 'channel' do + # assert_select '>title', 'Actions' + # assert_select '>description', "Actions for #{users(:admin_user).display_name}" + # assert_select 'item', 5 do + # assert_select 'title', /.+/ + # assert_select 'description', /.*/ + # end + # end + # end + # end + # + # def test_rss_feed_not_accessible_to_anonymous_user_without_token + # login_as nil + # get :index, { :format => "rss" } + # assert_response 401 + # end + # + # def test_rss_feed_not_accessible_to_anonymous_user_with_invalid_token + # login_as nil + # get :index, { :format => "rss", :token => 'foo' } + # assert_response 401 + # end + # + # def test_rss_feed_accessible_to_anonymous_user_with_valid_token + # login_as nil + # get :index, { :format => "rss", :token => users(:admin_user).token } + # assert_response :ok + # end + # + # def test_atom_feed_content + # login_as :admin_user + # get :index, { :format => "atom" } + # assert_equal 'application/atom+xml', @response.content_type + # # #puts @response.body + # + # assert_xml_select 'feed[xmlns="http://www.w3.org/2005/Atom"]' do + # assert_xml_select '>title', 'Actions' + # assert_xml_select '>subtitle', "Actions for #{users(:admin_user).display_name}" + # assert_xml_select 'entry', 11 do + # assert_xml_select 'title', /.+/ + # assert_xml_select 'content[type="html"]', /.*/ + # assert_xml_select 'published', /(#{Regexp.escape(todos(:book).updated_at.xmlschema)}|#{Regexp.escape(projects(:moremoney).updated_at.xmlschema)})/ + # end + # end + # end + # + # def test_atom_feed_not_accessible_to_anonymous_user_without_token + # login_as nil + # get :index, { :format => "atom" } + # assert_response 401 + # end + # + # def test_atom_feed_not_accessible_to_anonymous_user_with_invalid_token + # login_as nil + # get :index, { :format => "atom", :token => 'foo' } + # assert_response 401 + # end + # + # def test_atom_feed_accessible_to_anonymous_user_with_valid_token + # login_as nil + # get :index, { :format => "atom", :token => users(:admin_user).token } + # assert_response :ok + # end + # + # def test_text_feed_content + # login_as(:admin_user) + # get :index, { :format => "txt" } + # assert_equal 'text/plain', @response.content_type + # assert !(/ /.match(@response.body)) + # # #puts @response.body + # end + # + # def test_text_feed_not_accessible_to_anonymous_user_without_token + # login_as nil + # get :index, { :format => "txt" } + # assert_response 401 + # end + # + # def test_text_feed_not_accessible_to_anonymous_user_with_invalid_token + # login_as nil + # get :index, { :format => "txt", :token => 'foo' } + # assert_response 401 + # end + # + # def test_text_feed_accessible_to_anonymous_user_with_valid_token + # login_as nil + # get :index, { :format => "txt", :token => users(:admin_user).token } + # assert_response :ok + # end + # + # def test_ical_feed_content + # login_as :admin_user + # get :index, { :format => "ics" } + # assert_equal 'text/calendar', @response.content_type + # assert !(/ /.match(@response.body)) + # # #puts @response.body + # end + # + # def test_mobile_index_uses_text_html_content_type + # login_as(:admin_user) + # get :index, { :format => "m" } + # assert_equal 'text/html', @response.content_type + # end + # + # def test_mobile_index_assigns_down_count + # login_as(:admin_user) + # get :index, { :format => "m" } + # assert_equal 11, assigns['down_count'] + # end + # + # def test_mobile_create_action_creates_a_new_todo + # login_as(:admin_user) + # post :create, {"format"=>"m", "todo"=>{"context_id"=>"2", + # "due(1i)"=>"2007", "due(2i)"=>"1", "due(3i)"=>"2", + # "show_from(1i)"=>"", "show_from(2i)"=>"", "show_from(3i)"=>"", + # "project_id"=>"1", + # "notes"=>"test notes", "description"=>"test_mobile_create_action"}} + # t = Todo.find_by_description("test_mobile_create_action") + # assert_not_nil t + # assert_equal 2, t.context_id + # assert_equal 1, t.project_id + # assert t.active? + # assert_equal 'test notes', t.notes + # assert_nil t.show_from + # assert_equal Date.new(2007,1,2), t.due.to_date + # end + # + # def test_mobile_create_action_redirects_to_mobile_home_page_when_successful + # login_as(:admin_user) + # post :create, {"format"=>"m", "todo"=>{"context_id"=>"2", + # "due(1i)"=>"2007", "due(2i)"=>"1", "due(3i)"=>"2", + # "show_from(1i)"=>"", "show_from(2i)"=>"", "show_from(3i)"=>"", + # "project_id"=>"1", + # "notes"=>"test notes", "description"=>"test_mobile_create_action", "state"=>"0"}} + # assert_redirected_to '/mobile' + # end + # + # def test_mobile_create_action_renders_new_template_when_save_fails + # login_as(:admin_user) + # post :create, {"format"=>"m", "todo"=>{"context_id"=>"2", + # "due(1i)"=>"2007", "due(2i)"=>"1", "due(3i)"=>"2", + # "show_from(1i)"=>"", "show_from(2i)"=>"", "show_from(3i)"=>"", + # "project_id"=>"1", + # "notes"=>"test notes"}, "tag_list"=>"test, test2"} + # assert_template 'todos/new' + # end + # + # def test_toggle_check_on_recurring_todo + # login_as(:admin_user) + # + # # link todo_1 and recurring_todo_1 + # recurring_todo_1 = RecurringTodo.find(1) + # todo_1 = Todo.find_by_recurring_todo_id(1) + # + # # mark todo_1 as complete by toggle_check + # xhr :post, :toggle_check, :id => todo_1.id, :_source_view => 'todo' + # todo_1.reload + # assert todo_1.completed? + # + # # check that there is only one active todo belonging to recurring_todo + # count = Todo.count(:all, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'active'}) + # assert_equal 1, count + # + # # check there is a new todo linked to the recurring pattern + # next_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'active'}) + # assert_equal "Call Bill Gates every day", next_todo.description + # # check that the new todo is not the same as todo_1 + # assert_not_equal todo_1.id, next_todo.id + # + # # change recurrence pattern to monthly and set show_from 2 days before due + # # date this forces the next todo to be put in the tickler + # recurring_todo_1.show_from_delta = 2 + # recurring_todo_1.show_always = 0 + # recurring_todo_1.target = 'due_date' + # recurring_todo_1.recurring_period = 'monthly' + # recurring_todo_1.recurrence_selector = 0 + # recurring_todo_1.every_other1 = 1 + # recurring_todo_1.every_other2 = 2 + # recurring_todo_1.every_other3 = 5 + # # use assert to catch validation errors if present. we need to replace + # # this with a good factory implementation + # assert recurring_todo_1.save + # + # # mark next_todo as complete by toggle_check + # xhr :post, :toggle_check, :id => next_todo.id, :_source_view => 'todo' + # next_todo.reload + # assert next_todo.completed? + # + # # check that there are three todos belonging to recurring_todo: two + # # completed and one deferred + # count = Todo.count(:all, :conditions => {:recurring_todo_id => recurring_todo_1.id}) + # assert_equal 3, count + # + # # check there is a new todo linked to the recurring pattern in the tickler + # next_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'deferred'}) + # assert !next_todo.nil? + # assert_equal "Call Bill Gates every day", next_todo.description + # # check that the todo is in the tickler + # assert !next_todo.show_from.nil? + # end + # + # def test_toggle_check_on_rec_todo_show_from_today + # login_as(:admin_user) + # + # # link todo_1 and recurring_todo_1 + # recurring_todo_1 = RecurringTodo.find(1) + # set_user_to_current_time_zone(recurring_todo_1.user) + # todo_1 = Todo.find_by_recurring_todo_id(1) + # today = Time.zone.now.at_midnight + # + # # change recurrence pattern to monthly and set show_from to today + # recurring_todo_1.target = 'show_from_date' + # recurring_todo_1.recurring_period = 'monthly' + # recurring_todo_1.recurrence_selector = 0 + # recurring_todo_1.every_other1 = today.day + # recurring_todo_1.every_other2 = 1 + # assert recurring_todo_1.save + # + # # mark todo_1 as complete by toggle_check, this gets rid of todo_1 that was + # # not correctly created from the adjusted recurring pattern we defined + # # above. + # xhr :post, :toggle_check, :id => todo_1.id, :_source_view => 'todo' + # todo_1.reload + # assert todo_1.completed? + # + # # locate the new todo. This todo is created from the adjusted recurring + # # pattern defined in this test + # new_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'active'}) + # assert !new_todo.nil? + # + # # mark new_todo as complete by toggle_check + # xhr :post, :toggle_check, :id => new_todo.id, :_source_view => 'todo' + # new_todo.reload + # assert todo_1.completed? + # + # # locate the new todo in tickler + # new_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'deferred'}) + # assert !new_todo.nil? + # + # assert_equal "Call Bill Gates every day", new_todo.description + # # check that the new todo is not the same as todo_1 + # assert_not_equal todo_1.id, new_todo.id + # + # # check that the new_todo is in the tickler to show next month + # assert !new_todo.show_from.nil? + # + # # do not use today here. It somehow gets messed up with the timezone calculation. + # next_month = (Time.zone.now + 1.month).at_midnight + # + # assert_equal next_month.utc.to_date.to_s(:db), new_todo.show_from.utc.to_date.to_s(:db) + # end + # + # def test_check_for_next_todo + # login_as :admin_user + # + # recurring_todo_1 = RecurringTodo.find(5) + # @todo = Todo.find_by_recurring_todo_id(1) + # assert @todo.from_recurring_todo? + # # rewire @todo to yearly recurring todo + # @todo.recurring_todo_id = 5 + # + # # make todo due tomorrow and change recurring date also to tomorrow + # @todo.due = Time.zone.now + 1.day + # @todo.save + # recurring_todo_1.every_other1 = @todo.due.day + # recurring_todo_1.every_other2 = @todo.due.month + # recurring_todo_1.save + # + # # mark todo complete + # xhr :post, :toggle_check, :id => @todo.id, :_source_view => 'todo' + # @todo.reload + # assert @todo.completed? + # + # # check that there is no active todo + # next_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'active'}) + # assert next_todo.nil? + # + # # check for new deferred todo + # next_todo = Todo.find(:first, :conditions => {:recurring_todo_id => recurring_todo_1.id, :state => 'deferred'}) + # assert !next_todo.nil? + # # check that the due date of the new todo is later than tomorrow + # assert next_todo.due > @todo.due + # end + # + # def test_removing_hidden_project_activates_todo + # login_as(:admin_user) + # + # # get a project and hide it, todos in the project should be hidden + # p = projects(:timemachine) + # p.hide! + # assert p.reload().hidden? + # todo = p.todos.first + # assert_equal "project_hidden", todo.state + # + # # clear project from todo: the todo should be unhidden + # xhr :post, :update, :id => 5, :_source_view => 'todo', "project_name"=>"None", "todo"=>{} + # todo.reload() + # assert_equal "active", todo.state + # end + # + # def test_url_with_slash_in_query_string_are_parsed_correctly + # # See http://blog.swivel.com/code/2009/06/rails-auto_link-and-certain-query-strings.html + # login_as(:admin_user) + # user = users(:admin_user) + # todo = user.todos.first + # url = "http://example.com/foo?bar=/baz" + # todo.notes = "foo #{url} bar" + # todo.save! + # get :index + # assert_select("a[href=#{url}]") + # end + # + # def test_format_note_normal + # login_as(:admin_user) + # todo = users(:admin_user).todos.first + # todo.notes = "A normal description." + # todo.save! + # get :index + # assert_select("div#notes_todo_#{todo.id}", "A normal description.") + # end + # + # def test_format_note_markdown + # login_as(:admin_user) + # todo = users(:admin_user).todos.first + # todo.notes = "A *bold description*." + # todo.save! + # get :index + # assert_select("div#notes_todo_#{todo.id}", "A bold description.") + # assert_select("div#notes_todo_#{todo.id} strong", "bold description") + # end + # + # def test_format_note_link + # login_as(:admin_user) + # todo = users(:admin_user).todos.first + # todo.notes = "A link to http://github.com/." + # todo.save! + # get :index + # assert_select("div#notes_todo_#{todo.id}", 'A link to http://github.com/.') + # assert_select("div#notes_todo_#{todo.id} a[href=http://github.com/]", 'http://github.com/') + # end + # + # def test_format_note_link_message + # login_as(:admin_user) + # todo = users(:admin_user).todos.first + # todo.raw_notes = "A Mail.app message:// link" + # todo.save! + # get :index + # assert_select("div#notes_todo_#{todo.id}", 'A Mail.app message://<ABCDEF-GHADB-123455-FOO-BAR@example.com> link') + # assert_select("div#notes_todo_#{todo.id} a", 'message://<ABCDEF-GHADB-123455-FOO-BAR@example.com>') + # assert_select("div#notes_todo_#{todo.id} a[href=message://<ABCDEF-GHADB-123455-FOO-BAR@example.com>]", 'message://<ABCDEF-GHADB-123455-FOO-BAR@example.com>') + # end + # + # def test_format_note_link_onenote + # login_as(:admin_user) + # todo = users(:admin_user).todos.first + # todo.notes = ' "link me to onenote":onenote:///E:\OneNote\dir\notes.one#PAGE§ion-id={FD597D3A-3793-495F-8345-23D34A00DD3B}&page-id={1C95A1C7-6408-4804-B3B5-96C28426022B}&end' + # todo.save! + # get :index + # assert_select("div#notes_todo_#{todo.id}", 'link me to onenote') + # assert_select("div#notes_todo_#{todo.id} a", 'link me to onenote') + # assert_select("div#notes_todo_#{todo.id} a[href=onenote:///E:\\OneNote\\dir\\notes.one#PAGE&section-id={FD597D3A-3793-495F-8345-23D34A00DD3B}&page-id={1C95A1C7-6408-4804-B3B5-96C28426022B}&end]", 'link me to onenote') + # end + # + # def test_get_boolean_expression_from_parameters_of_tag_view_single_tag + # login_as(:admin_user) + # get :tag, :name => "single" + # assert_equal true, assigns['single_tag'], "should recognize it is a single tag name" + # assert_equal "single", assigns['tag_expr'][0][0], "should store the single tag" + # assert_equal "single", assigns['tag_name'], "should store the single tag name" + # end + # + # def test_get_boolean_expression_from_parameters_of_tag_view_multiple_tags + # login_as(:admin_user) + # get :tag, :name => "multiple", :and => "tags", :and1 => "present", :and2 => "here" + # assert_equal false, assigns['single_tag'], "should recognize it has multiple tags" + # assert_equal 4, assigns['tag_expr'].size, "should have 4 AND expressions" + # end + # + # def test_get_boolean_expression_from_parameters_of_tag_view_multiple_tags_without_digitless_and + # login_as(:admin_user) + # get :tag, :name => "multiple", :and1 => "tags", :and2 => "present", :and3 => "here" + # assert_equal false, assigns['single_tag'], "should recognize it has multiple tags" + # assert_equal 4, assigns['tag_expr'].size, "should have 4 AND expressions" + # end + # + # def test_get_boolean_expression_from_parameters_of_tag_view_multiple_ORs + # login_as(:admin_user) + # get :tag, :name => "multiple,tags,present" + # assert_equal false, assigns['single_tag'], "should recognize it has multiple tags" + # assert_equal 1, assigns['tag_expr'].size, "should have 1 expressions" + # assert_equal 3, assigns['tag_expr'][0].size, "should have 3 ORs in 1st expression" + # end + # + # def test_get_boolean_expression_from_parameters_of_tag_view_multiple_ORs_and_ANDS + # login_as(:admin_user) + # get :tag, :name => "multiple,tags,present", :and => "here,is,two", :and1=>"and,three" + # assert_equal false, assigns['single_tag'], "should recognize it has multiple tags" + # assert_equal 3, assigns['tag_expr'].size, "should have 3 expressions" + # assert_equal 3, assigns['tag_expr'][0].size, "should have 3 ORs in 1st expression" + # assert_equal 3, assigns['tag_expr'][1].size, "should have 3 ORs in 2nd expression" + # assert_equal 2, assigns['tag_expr'][2].size, "should have 2 ORs in 3rd expression" + # end + # + # def test_set_right_title + # login_as(:admin_user) + # + # get :tag, :name => "foo" + # assert_equal "foo", assigns['tag_title'] + # get :tag, :name => "foo,bar", :and => "baz" + # assert_equal "foo,bar AND baz", assigns['tag_title'] + # end + # + # def test_set_default_tag + # login_as(:admin_user) + # + # get :tag, :name => "foo" + # assert_equal "foo", assigns['initial_tags'] + # get :tag, :name => "foo,bar", :and => "baz" + # assert_equal "foo", assigns['initial_tags'] + # end + # + # def test_tag_text_feed_not_accessible_to_anonymous_user_without_token + # login_as nil + # get :tag, {:name => "foo", :format => "txt" } + # assert_response 401 + # end + # + # def test_make_todo_dependent + # login_as(:admin_user) + # + # predecessor = todos(:call_bill) + # successor = todos(:call_dino_ext) + # + # # no predecessors yet + # assert_equal 0, successor.predecessors.size + # + # # add predecessor + # put :add_predecessor, :predecessor=>predecessor.id, :successor=>successor.id + # + # assert_equal 1, successor.predecessors.count + # assert_equal predecessor.id, successor.predecessors.first.id + # end + # + # def test_make_todo_with_dependencies_dependent + # login_as(:admin_user) + # + # predecessor = todos(:call_bill) + # successor = todos(:call_dino_ext) + # other_todo = todos(:phone_grandfather) + # + # # predecessor -> successor + # put :add_predecessor, :predecessor=>predecessor.id, :successor=>successor.id + # + # # other_todo -> predecessor -> successor + # put :add_predecessor, :predecessor=>other_todo.id, :successor=>predecessor.id + # + # assert_equal 1, successor.predecessors(true).count + # assert_equal 0, other_todo.predecessors(true).count + # assert_equal 1, predecessor.predecessors(true).count + # assert_equal predecessor.id, successor.predecessors.first.id + # assert_equal other_todo.id, predecessor.predecessors.first.id + # end + # + # def test_mingle_dependent_todos_leave + # # based on #1271 + # login_as(:admin_user) + # + # t1 = todos(:call_bill) + # t2 = todos(:call_dino_ext) + # t3 = todos(:phone_grandfather) + # t4 = todos(:construct_dilation_device) + # + # # t1 -> t2 + # put :add_predecessor, :predecessor=>t1.id, :successor=>t2.id + # # t3 -> t4 + # put :add_predecessor, :predecessor=>t3.id, :successor=>t4.id + # + # # t2 -> t4 + # put :add_predecessor, :predecessor=>t2.id, :successor=>t4.id + # + # # should be: t1 -> t2 -> t4 and t3 -> t4 + # assert t4.predecessors.map(&:id).include?(t2.id) + # assert t4.predecessors.map(&:id).include?(t3.id) + # assert t2.predecessors.map(&:id).include?(t1.id) + # end + # + # def test_mingle_dependent_todos_root + # # based on #1271 + # login_as(:admin_user) + # + # t1 = todos(:call_bill) + # t2 = todos(:call_dino_ext) + # t3 = todos(:phone_grandfather) + # t4 = todos(:construct_dilation_device) + # + # # t1 -> t2 + # put :add_predecessor, :predecessor=>t1.id, :successor=>t2.id + # # t3 -> t4 + # put :add_predecessor, :predecessor=>t3.id, :successor=>t4.id + # + # # t3 -> t2 + # put :add_predecessor, :predecessor=>t3.id, :successor=>t2.id + # + # # should be: t1 -> t2 and t3 -> t4 & t2 + # assert t3.successors.map(&:id).include?(t4.id) + # assert t3.successors.map(&:id).include?(t2.id) + # assert t2.predecessors.map(&:id).include?(t1.id) + # assert t2.predecessors.map(&:id).include?(t3.id) + # end + # + # def test_unmingle_dependent_todos + # # based on #1271 + # login_as(:admin_user) + # + # t1 = todos(:call_bill) + # t2 = todos(:call_dino_ext) + # t3 = todos(:phone_grandfather) + # t4 = todos(:construct_dilation_device) + # + # # create same dependency tree as previous test + # # should be: t1 -> t2 -> t4 and t3 -> t4 + # put :add_predecessor, :predecessor=>t1.id, :successor=>t2.id + # put :add_predecessor, :predecessor=>t3.id, :successor=>t4.id + # put :add_predecessor, :predecessor=>t2.id, :successor=>t4.id + # + # # removing t4 as successor of t2 should leave t4 blocked with t3 as predecessor + # put :remove_predecessor, :predecessor=>t2.id, :id=>t4.id + # + # t4.reload + # assert t4.pending?, "t4 should remain pending" + # assert t4.predecessors.map(&:id).include?(t3.id) + # end end diff --git a/test/functional/users_controller_test.rb b/test/functional/users_controller_test.rb index 9a81f39c..dc065099 100644 --- a/test/functional/users_controller_test.rb +++ b/test/functional/users_controller_test.rb @@ -1,23 +1,10 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require 'users_controller' - -# Re-raise errors caught by the controller. -class UsersController; def rescue_action(e) raise e end; end class UsersControllerTest < ActionController::TestCase - fixtures :preferences, :users - - def setup - assert_equal "test", ENV['RAILS_ENV'] - assert_equal "change-me", Tracks::Config.salt - @controller = UsersController.new - @request = ActionController::TestRequest.new - @response = ActionController::TestResponse.new - end def test_get_index_when_not_logged_in get :index - assert_redirected_to :controller => 'login', :action => 'login' + assert_redirected_to login_path end def test_get_index_by_nonadmin @@ -32,7 +19,7 @@ class UsersControllerTest < ActionController::TestCase assert_response :success assert_equal "TRACKS::Manage Users", assigns['page_title'] assert_equal 5, assigns['total_users'] - assert_equal "/users", session['return-to'] + assert_equal users_url, session['return-to'] end def test_index_pagination_page_1 @@ -59,7 +46,7 @@ class UsersControllerTest < ActionController::TestCase def test_update_password_successful get :change_password # should fail because no login - assert_redirected_to :controller => 'login', :action => 'login' + assert_redirected_to login_path login_as :admin_user @user = @request.session['user_id'] get :change_password # should now pass because we're logged in @@ -74,21 +61,19 @@ class UsersControllerTest < ActionController::TestCase def test_update_password_no_confirmation post :update_password # should fail because no login - assert_redirected_to :controller => 'login', :action => 'login' + assert_redirected_to login_path login_as :admin_user post :update_password, :user => {:password => 'newpassword', :password_confirmation => 'wrong'} - assert_redirected_to :controller => 'users', :action => 'change_password' - assert users(:admin_user).save, false + assert_redirected_to change_password_user_path(users(:admin_user)) assert_equal 'Validation failed: Password doesn\'t match confirmation', flash[:error] end def test_update_password_validation_errors post :update_password # should fail because no login - assert_redirected_to :controller => 'login', :action => 'login' + assert_redirected_to login_path login_as :admin_user post :update_password, :user => {:password => 'ba', :password_confirmation => 'ba'} - assert_redirected_to :controller => 'users', :action => 'change_password' - assert users(:admin_user).save, false + assert_redirected_to change_password_user_path(User.find(users(:admin_user).id)) # For some reason, no errors are being raised now. #assert_equal 1, users(:admin_user).errors.count #assert_equal users(:admin_user).errors.on(:password), "is too short (min is 5 characters)" diff --git a/test/test_helper.rb b/test/test_helper.rb index 359a74f2..48338644 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -2,7 +2,8 @@ ENV["RAILS_ENV"] = "test" require File.expand_path('../../config/environment', __FILE__) require 'rails/test_help' -{ :salt => "change-me", :authentication_schemes => ["database", "open_id"], :prefered_auth => "database"}.each{|k,v| SITE_CONFIG[k]=v} +# set config for tests. Overwrite those read from config/site.yml. Use inject to avoid warning about changing CONSTANT +{"salt" => "change-me", "authentication_schemes" => ["database", "open_id", "ldap"], "prefered_auth" => "database"}.inject( SITE_CONFIG ) { |h, elem| h[elem[0]] = elem[1]; h } class ActiveSupport::TestCase # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order. @@ -10,17 +11,35 @@ class ActiveSupport::TestCase # Note: You'll currently still have to declare fixtures explicitly in integration tests # -- they do not yet inherit this setting fixtures :all - + # Add more helper methods to be used by all tests here... def assert_value_changed(object, method = nil) initial_value = object.send(method) yield assert_not_equal initial_value, object.send(method), "#{object}##{method}" end + # Generates a random string of ascii characters (a-z, "1 0") + # of a given length for testing assignment to fields + # for validation purposes + # + def generate_random_string(length) + string = "" + characters = %w(a b c d e f g h i j k l m n o p q r s t u v w z y z 1\ 0) + length.times do + pick = characters[rand(26)] + string << pick + end + return string + end + + def assert_equal_dmy(date1, date2) + assert_equal date1.strftime("%d-%m-%y"), date2.strftime("%d-%m-%y") + end end class ActionController::TestCase + def login_as(user) @request.session['user_id'] = user ? users(user).id : nil end @@ -61,26 +80,4 @@ class ActionController::TestCase eval("#{get_model_class}.count") end -end - -class ActiveSupport::TestCase - - # Generates a random string of ascii characters (a-z, "1 0") - # of a given length for testing assignment to fields - # for validation purposes - # - def generate_random_string(length) - string = "" - characters = %w(a b c d e f g h i j k l m n o p q r s t u v w z y z 1\ 0) - length.times do - pick = characters[rand(26)] - string << pick - end - return string - end - - def assert_equal_dmy(date1, date2) - assert_equal date1.strftime("%d-%m-%y"), date2.strftime("%d-%m-%y") - end - end \ No newline at end of file diff --git a/test/unit/context_test.rb b/test/unit/context_test.rb index dc5f2559..9fa7c114 100644 --- a/test/unit/context_test.rb +++ b/test/unit/context_test.rb @@ -54,12 +54,6 @@ class ContextTest < ActiveSupport::TestCase assert_equal @agenda.name, @agenda.title end - def test_feed_options - opts = Context.feed_options(users(:admin_user)) - assert_equal 'Tracks Contexts', opts[:title], 'Unexpected value for :title key of feed_options' - assert_equal 'Lists all the contexts for Admin Schmadmin', opts[:description], 'Unexpected value for :description key of feed_options' - end - def test_hidden_attr_reader assert !@agenda.hidden? @agenda.hide = true diff --git a/test/unit/project_test.rb b/test/unit/project_test.rb index b8570b16..53e178ef 100644 --- a/test/unit/project_test.rb +++ b/test/unit/project_test.rb @@ -128,12 +128,6 @@ class ProjectTest < ActiveSupport::TestCase assert p.nil? assert_nil p.id end - - def test_feed_options - opts = Project.feed_options(users(:admin_user)) - assert_equal 'Tracks Projects', opts[:title], 'Unexpected value for :title key of feed_options' - assert_equal 'Lists all the projects for Admin Schmadmin', opts[:description], 'Unexpected value for :description key of feed_options' - end def test_name_removes_extra_spaces newproj = Project.new diff --git a/test/unit/todo_test.rb b/test/unit/todo_test.rb index cedaaeb7..4d3acf6c 100644 --- a/test/unit/todo_test.rb +++ b/test/unit/todo_test.rb @@ -1,5 +1,4 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -require 'date' class TodoTest < ActiveSupport::TestCase fixtures :todos, :recurring_todos, :users, :contexts, :preferences, :tags, :taggings, :projects diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb index d5ab917e..da51de18 100644 --- a/test/unit/user_test.rb +++ b/test/unit/user_test.rb @@ -1,13 +1,5 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper') -module Tracks - class Config - def self.auth_schemes - ['database', 'ldap'] - end - end -end - class SimpleLdapAuthenticator cattr_accessor :fake_success @@ -22,7 +14,7 @@ class UserTest < ActiveSupport::TestCase def setup assert_equal "test", ENV['RAILS_ENV'] assert_equal "change-me", Tracks::Config.salt - assert_equal ['database', 'ldap'], Tracks::Config.auth_schemes + assert Tracks::Config.auth_schemes.include?('ldap') @admin_user = User.find(1) @other_user = User.find(2) end