Merge branch 'master' of git://github.com/bsag/tracks

Signed-off-by: Reinier Balt <lrbalt@gmail.com>
This commit is contained in:
Reinier Balt 2008-11-14 11:48:54 +01:00
commit dd56c86f78
25 changed files with 320 additions and 67 deletions

View file

@ -115,7 +115,7 @@ class ApplicationController < ActionController::Base
def format_date(date)
if date
date_format = prefs.date_format
formatted_date = date.strftime("#{date_format}")
formatted_date = date.in_time_zone(prefs.time_zone).strftime("#{date_format}")
else
formatted_date = ''
end
@ -170,11 +170,12 @@ class ApplicationController < ActionController::Base
# set dates
todo.recurring_todo_id = rt.id
todo.due = rt.get_due_date(date)
# make sure that show_from is not in the past
show_from_date = rt.get_show_from_date(date)
if show_from_date.nil?
todo.show_from=nil
else
# make sure that show_from is not in the past
todo.show_from = show_from_date < Time.zone.now ? nil : show_from_date
end

View file

@ -186,6 +186,13 @@ class ProjectsController < ApplicationController
init_not_done_counts(['project'])
end
def actionize
@state = params['state']
@projects = current_user.projects.actionize(current_user.id, :state => @state) if @state
@contexts = current_user.contexts
init_not_done_counts(['project'])
end
protected
def render_projects_html

View file

@ -10,6 +10,7 @@ class TodosController < ApplicationController
session :off, :only => :index, :if => Proc.new { |req| is_feed_request(req) }
def index
current_user.deferred_todos.find_and_activate_ready
@projects = current_user.projects.find(:all, :include => [:default_context])
@contexts = current_user.contexts.find(:all)
@ -133,7 +134,7 @@ class TodosController < ApplicationController
@saved = @todo.toggle_completion!
# check if this todo has a related recurring_todo. If so, create next todo
check_for_next_todo if @saved
@new_recurring_todo = check_for_next_todo(@todo) if @saved
respond_to do |format|
format.js do
@ -278,7 +279,7 @@ class TodosController < ApplicationController
@project_id = @todo.project_id
# check if this todo has a related recurring_todo. If so, create next todo
check_for_next_todo
@new_recurring_todo = check_for_next_todo(@todo)
@saved = @todo.destroy
@ -382,7 +383,7 @@ class TodosController < ApplicationController
@not_done_todos = tag_collection.find(:all,
:conditions => ['taggings.user_id = ? and state = ?', current_user.id, 'active'],
:order => 'todos.completed_at DESC, todos.created_at DESC')
:order => 'todos.due IS NULL, todos.due ASC, todos.created_at ASC')
@hidden_todos = current_user.todos.find(:all,
:include => [:taggings, :tags, :context],
:conditions => ['tags.name = ? AND (todos.state = ? OR (contexts.hide = ? AND todos.state = ?))', @tag_name, 'project_hidden', true, 'active'],
@ -390,6 +391,7 @@ class TodosController < ApplicationController
@deferred = tag_collection.find(:all,
:conditions => ['taggings.user_id = ? and state = ?', current_user.id, 'deferred'],
:order => 'show_from ASC, todos.created_at DESC')
# If you've set no_completed to zero, the completed items box isn't shown on
# the tag page
max_completed = current_user.prefs.show_number_completed
@ -770,33 +772,34 @@ class TodosController < ApplicationController
['rss','atom','txt','ics'].include?(req.parameters[:format])
end
def check_for_next_todo
def check_for_next_todo(todo)
# check if this todo has a related recurring_todo. If so, create next todo
@new_recurring_todo = nil
@recurring_todo = nil
if @todo.from_recurring_todo?
@recurring_todo = current_user.recurring_todos.find(@todo.recurring_todo_id)
new_recurring_todo = nil
recurring_todo = nil
if todo.from_recurring_todo?
recurring_todo = current_user.recurring_todos.find(todo.recurring_todo_id)
# check for next todo either from the due date or the show_from date
date_to_check = @todo.due.nil? ? @todo.show_from : @todo.due
date_to_check = todo.due.nil? ? todo.show_from : todo.due
# if both due and show_from are nil, check for a next todo with yesterday
# as reference point. We pick yesterday so that new todos for today will
# be created instead of new todos for tomorrow.
date_to_check = Time.zone.now-1.day if date_to_check.nil?
# if both due and show_from are nil, check for a next todo from now
date_to_check = Time.zone.now if date_to_check.nil?
if @recurring_todo.active? && @recurring_todo.has_next_todo(date_to_check)
if recurring_todo.active? && recurring_todo.has_next_todo(date_to_check)
# shift the reference date to yesterday if date_to_check is furher in
# the past. This is to make sure we do not get older todos for overdue
# todos. I.e. checking a daily todo that is overdue with 5 days will
# create a new todo which is overdue by 4 days if we don't shift the
# date. Discard the time part in the compare
# date. Discard the time part in the compare. We pick yesterday so that
# new todos due for today will be created instead of new todos for
# tomorrow.
date = date_to_check.at_midnight >= Time.zone.now.at_midnight ? date_to_check : Time.zone.now-1.day
@new_recurring_todo = create_todo_from_recurring_todo(@recurring_todo, date)
new_recurring_todo = create_todo_from_recurring_todo(recurring_todo, date)
end
end
end
return new_recurring_todo
end
def get_due_id_for_calendar(due)

View file

@ -281,7 +281,7 @@ module TodosHelper
end
def defer_link(days)
link_to_remote image_tag("defer_#{days}.png"), :url => {:controller => 'todos', :action => 'defer', :id => @todo.id, :days => days, :_source_view => (@source_view.underscore.gsub(/\s+/,'_') rescue "")}
link_to_remote image_tag("defer_#{days}.png", :alt => "Defer #{pluralize(days, 'day')}"), :url => {:controller => 'todos', :action => 'defer', :id => @todo.id, :days => days, :_source_view => (@source_view.underscore.gsub(/\s+/,'_') rescue "")}
end
end

View file

@ -495,12 +495,14 @@ class RecurringTodo < ActiveRecord::Base
def get_xth_day_of_month(x, weekday, month, year)
if x == 5
# last -> count backwards
last_day = Time.zone.local(year, month, Time.days_in_month(month))
# last -> count backwards. use UTC to avoid strange timezone oddities
# where last_day -= 1.day seems to shift tz+0100 to tz+0000
last_day = Time.utc(year, month, Time.days_in_month(month))
while last_day.wday != weekday
last_day -= 1.day
end
return last_day
# convert back to local timezone
return Time.zone.local(last_day.year, last_day.month, last_day.day)
else
# 1-4th -> count upwards
start = Time.zone.local(year,month,1)
@ -517,17 +519,19 @@ class RecurringTodo < ActiveRecord::Base
end
def get_yearly_date(previous)
start = determine_start(previous)
day = self.every_other1
month = self.every_other2
case self.recurrence_selector
when 0 # specific day of a specific month
# if there is no next month n in this year, search in next year
if start.month >= month
start = Time.zone.local(start.year+1, month, 1) if start.day >= day
start = Time.zone.local(start.year, month, 1) if start.day <= day
if start.month > month || (start.month == month && start.day >= day)
# if there is no next month n and day m in this year, search in next
# year
start = Time.zone.local(start.year+1, month, 1)
else
# if there is a next month n, stay in this year
start = Time.zone.local(start.year, month, 1)
end
return Time.zone.local(start.year, month, day)

View file

@ -51,6 +51,21 @@ class User < ActiveRecord::Base
self.update_positions(projects.map{ |p| p.id })
return projects
end
def actionize(user_id, scope_conditions = {})
@state = scope_conditions[:state]
query_state = ""
query_state = "AND project.state = '" + @state +"' "if @state
projects = Project.find_by_sql([
"SELECT project.id, count(todo.id) as p_count " +
"FROM projects as project " +
"LEFT OUTER JOIN todos as todo ON todo.project_id = project.id "+
"WHERE project.user_id = ? AND NOT todo.state='completed' " +
query_state +
" GROUP BY project.id ORDER by p_count DESC",user_id])
self.update_positions(projects.map{ |p| p.id })
projects = find(:all, :conditions => scope_conditions)
return projects
end
end
has_many :active_projects,
:class_name => 'Project',

View file

@ -8,9 +8,9 @@ the newly created action.
*)
(* Edit appropriately for your setup *)
property myUsername to "<%= current_user.login %>"
property myToken to "<%= current_user.token %>"
property myContextID to <%= context.id %> (* <%= context.name %> *)
property myUsername : "<%= current_user.login %>"
property myToken : "<%= current_user.token %>"
property myContextID : <%= context.id %> (* <%= context.name %> *)
-- this string is used when the message subject is empty
property emptySubject : "No Subject Specified"

View file

@ -1,7 +1,8 @@
<div class="project-state-group" id="list-<%= state %>-projects-container" <%= " style=\"display:none\"" if project_state_group.empty? %>>
<h2><span id="<%= state %>-projects-count" class="badge"><%= project_state_group.length %></span><%= state.titlecase %> Projects</h2>
<div class="menu_sort"><span class="sort_separator">Sort&nbsp;</span>
<div class="alpha_sort">
<%= link_to("Sort Alphabetically", alphabetize_projects_path(:state => state),
<%= link_to("Alphabetically", alphabetize_projects_path(:state => state),
:class => "alphabetize_link", :title => "Sort these projects alphabetically") %>
<% apply_behavior '.alphabetize_link:click', :prevent_default => true do |page, element|
page.confirming 'Are you sure that you want to sort these projects alphabetically? This will replace the existing sort order.' do
@ -10,10 +11,21 @@
page << remote_to_href(:complete => "alphaSort.stopWaiting()")
end
end
%></div><span class="sort_separator">&nbsp;|&nbsp;</span><div class="tasks_sort">
<%= link_to("By number of tasks", actionize_projects_path(:state => state),
:class => "actionize_link", :title => "Sort these projects by number of tasks") %>
<% apply_behavior '.actionize_link:click', :prevent_default => true do |page, element|
page.confirming 'Are you sure that you want to sort these projects by the number of tasks? This will replace the existing sort order.' do
page << "tasksSort = this.up('.tasks_sort');
tasksSort.startWaiting();"
page << remote_to_href(:complete => "tasksSort.stopWaiting()")
end
end
%></div>
</div>
<div id="list-<%= state %>-projects" class="project-list">
<%= render :partial => 'project_listing', :collection => project_state_group %>
</div>
<%= sortable_element "list-#{state}-projects", get_listing_sortable_options("list-#{state}-projects") %>
</div>
</div>

View file

@ -0,0 +1,6 @@
list_id = "list-#{@state}-projects"
page.replace_html list_id,
:partial => 'project_listing',
:collection => @projects
page.sortable list_id, get_listing_sortable_options(list_id)

View file

@ -33,8 +33,8 @@ end %>
<h2><label for="tag_list">Tags (separate with commas)</label></h2>
<%= text_field_tag "tag_list", @tag_list_text, :size => 30, :tabindex => 6 %>
<h2><label for="todo_due">Due</label></h2>
<%= date_select("todo", "due", :order => [:day, :month, :year],
:start_year => this_year, :include_blank => true) %>
<%= date_select("todo", "due", {:order => [:day, :month, :year],
:start_year => this_year, :include_blank => true}, :tabindex => 7) %>
<h2><label for="todo_show_from">Show from</label></h2>
<%= date_select("todo", "show_from", :order => [:day, :month, :year],
:start_year => this_year, :include_blank => true) %>
<%= date_select("todo", "show_from", {:order => [:day, :month, :year],
:start_year => this_year, :include_blank => true}, :tabindex => 8) %>

View file

@ -1,5 +1,5 @@
<% form_tag formatted_todos_path(:m), :method => :post do %>
<%= render :partial => 'edit_mobile' %>
<p><input type="submit" value="Create" tabindex="6" accesskey="#" /></p>
<p><input type="submit" value="Create" tabindex="12" accesskey="#" /></p>
<% end -%>
<%= link_to "Back", @return_path %>

View file

@ -28,6 +28,10 @@ ActionController::Routing::Routes.draw do |map|
projects.resources :todos, :name_prefix => "project_"
end
map.resources :projects, :collection => {:order => :post, :actionize => :post} do |projects|
projects.resources :todos, :name_prefix => "project_"
end
map.resources :todos,
:member => {:toggle_check => :put, :toggle_star => :put},
:collection => {:check_deferred => :post, :filter_to_context => :post, :filter_to_project => :post}

View file

@ -6,14 +6,26 @@ class ChangeDatesToDatetimes < ActiveRecord::Migration
change_column :recurring_todos, :end_date, :datetime
User.all(:include => [:todos, :recurring_todos]).each do |user|
if !user.prefs ## ugly hack for strange edge-case of not having preferences object
user.instance_eval do
def at_midnight(date)
return Time.zone.local(date.year, date.month, date.day, 0, 0, 0)
end
def time
Time.zone.now
end
end
end
user.todos.each do |todo|
todo.update_attribute(:show_from, user.at_midnight(todo.show_from)) unless todo.show_from.nil?
todo.update_attribute(:due, user.at_midnight(todo.due)) unless todo.due.nil?
todo[:show_from] = user.at_midnight(todo.show_from) unless todo.show_from.nil?
todo[:due] = user.at_midnight(todo.due) unless todo.due.nil?
todo.save_with_validation(false)
end
user.recurring_todos.each do |todo|
todo.update_attribute(:start_from, user.at_midnight(todo.start_from)) unless todo.start_from.nil?
todo.update_attribute(:end_date, user.at_midnight(todo.end_date)) unless todo.end_date.nil?
todo[:start_from] = user.at_midnight(todo.start_from) unless todo.start_from.nil?
todo[:end_date] = user.at_midnight(todo.end_date) unless todo.end_date.nil?
todo.save_with_validation(false)
end
end
end

View file

@ -22,6 +22,7 @@ New features:
4. New interface to import an email / sms messages into Tracks (needs an email server on the same server as Tracks)
5. New buttons to quickly defer an action 1 or 7 days
6. Calendar view to review due actions, includes iCal feed to use in your calendar app (tested with Google Calendar, Evolution, Outlook 2007)
7. You can now sort projects on number of active todos
Under the hood:
1. Move selenium tests to RSpec

View file

@ -692,11 +692,14 @@ div#list-active-projects, div#list-hidden-projects, div#list-completed-projects,
margin:20px 0px 8px 13px
}
div.alpha_sort {
div.menu_sort {
margin-top:-20px;
float:right;
}
div.alpha_sort, div.tasks_sort,span.sort_separator {
float:left;
}
.container td {
border: none;

View file

@ -129,7 +129,8 @@ div.buttons, div.buttons a, div.buttons a:hover {text-align: right; margin-right
div#list-active-projects, div#list-hidden-projects, div#list-completed-projects, div#list-contexts, div#projects-empty-nd {clear:right; border: 1px solid #999}
.project-state-group h2 {margin:20px 0px 8px 13px}
.search-result-group h2 {margin:20px 0px 8px 13px }
div.alpha_sort {margin-top:-20px; float:right}
div.menu_sort {margin-top:-20px; float:right}
div.alpha_sort, div.tasks_sort,span.sort_separator {float:left}
.container td {border: none; padding-bottom: 5px}
.container form {border: none}
div.project_description {background: #eee; padding: 5px; margin-top: 0px; margin-left: -5px; margin-right: -5px; color: #666; font-style: italic; font-size: 12px; font-weight: normal}

View file

@ -230,3 +230,17 @@ end
completed_at: ~
show_from: <%= next_week %>
user_id: 2
18:
id: 18
user_id: 1
context_id: 1
project_id: 2
description: Call Bill Gates every day
notes: ~
state: active
created_at: <%= last_week %>
due: <%= last_week %>
completed_at: ~
show_from: ~
recurring_todo_id: 1

View file

@ -218,6 +218,15 @@ class ProjectsControllerTest < TodoContainerControllerTestBase
get :index, { :format => "txt", :token => users(:admin_user).token }
assert_response :ok
end
def test_actionize_sorts_active_projects_by_number_of_tasks
login_as :admin_user
u = users(:admin_user)
post :actionize, :state => "active", :format => 'js'
assert_equal 1, projects(:gardenclean).position
assert_equal 2, projects(:timemachine).position
assert_equal 3, projects(:moremoney).position
end
def test_alphabetize_sorts_active_projects_alphabetically
login_as :admin_user

View file

@ -79,6 +79,11 @@ class RecurringTodosControllerTest < ActionController::TestCase
recurring_todo_1 = RecurringTodo.find(1)
assert recurring_todo_1.completed?
# remove remaining todo
todo = Todo.find_by_recurring_todo_id(1)
todo.recurring_todo_id = 2
todo.save
todo_count = Todo.count
# mark as active
@ -120,4 +125,59 @@ class RecurringTodosControllerTest < ActionController::TestCase
assert_equal nil, new_todo.show_from
end
def test_last_sunday_of_march
# this test is a duplicate of the unit test. Only this test covers the
# codepath in the controllers
login_as(:admin_user)
orig_rt_count = RecurringTodo.count
orig_todo_count = Todo.count
put :create,
"context_name"=>"library",
"project_name"=>"Build a working time machine",
"recurring_todo" =>
{
"daily_every_x_days"=>"1",
"daily_selector"=>"daily_every_x_day",
"description"=>"new recurring pattern",
"end_date" => "",
"ends_on" => "no_end_date",
"monthly_day_of_week" => "1",
"monthly_every_x_day" => "22",
"monthly_every_x_month2" => "1",
"monthly_every_x_month" => "1",
"monthly_every_xth_day"=>"1",
"monthly_selector"=>"monthly_every_x_day",
"notes"=>"with some notes",
"number_of_occurences" => "",
"recurring_period"=>"yearly",
"recurring_show_days_before"=>"0",
"recurring_target"=>"due_date",
"start_from"=>"",
"weekly_every_x_week"=>"1",
"weekly_return_monday"=>"w",
"yearly_day_of_week"=>"0",
"yearly_every_x_day"=>"22",
"yearly_every_xth_day"=>"5",
"yearly_month_of_year2"=>"3",
"yearly_month_of_year"=>"10",
"yearly_selector"=>"yearly_every_xth_day"
},
"tag_list"=>"one, two, three, four"
# check new recurring todo added
assert_equal orig_rt_count+1, RecurringTodo.count
# check new todo added
assert_equal orig_todo_count+1, Todo.count
# find the newly created todo
new_todo = Todo.find_by_description("new recurring pattern")
assert !new_todo.nil?
# the date should be 29 march 2009
assert_equal Time.zone.local(2009,3,29), new_todo.due
end
end

View file

@ -56,7 +56,7 @@ class StatsControllerTest < Test::Unit::TestCase
assert_equal 3, assigns['projects'].count
assert_equal 3, assigns['projects'].count(:conditions => "state = 'active'")
assert_equal 10, assigns['contexts'].count
assert_equal 15, assigns['actions'].count
assert_equal 16, assigns['actions'].count
assert_equal 4, assigns['tags'].count
assert_equal 2, assigns['unique_tags'].size
assert_equal 2.week.ago.utc.beginning_of_day, assigns['first_action'].created_at

View file

@ -124,9 +124,9 @@ class TodosControllerTest < Test::Rails::TestCase
def test_update_todo_to_deferred_is_reflected_in_badge_count
login_as(:admin_user)
get :index
assert_equal 10, assigns['count']
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 9, assigns['down_count']
assert_equal 10, assigns['down_count']
end
def test_update_todo
@ -188,7 +188,7 @@ class TodosControllerTest < Test::Rails::TestCase
assert_select '>description', "Actions for #{users(:admin_user).display_name}"
assert_select 'language', 'en-us'
assert_select 'ttl', '40'
assert_select 'item', 10 do
assert_select 'item', 11 do
assert_select 'title', /.+/
assert_select 'description', /.*/
assert_select 'link', %r{http://test.host/contexts/.+}
@ -242,7 +242,7 @@ class TodosControllerTest < Test::Rails::TestCase
assert_xml_select 'feed[xmlns="http://www.w3.org/2005/Atom"]' do
assert_xml_select '>title', 'Tracks Actions'
assert_xml_select '>subtitle', "Actions for #{users(:admin_user).display_name}"
assert_xml_select 'entry', 10 do
assert_xml_select 'entry', 11 do
assert_xml_select 'title', /.+/
assert_xml_select 'content[type="html"]', /.*/
assert_xml_select 'published', /(#{Regexp.escape(projects(:timemachine).updated_at.xmlschema)}|#{Regexp.escape(projects(:moremoney).updated_at.xmlschema)})/
@ -311,7 +311,7 @@ class TodosControllerTest < Test::Rails::TestCase
def test_mobile_index_assigns_down_count
login_as(:admin_user)
get :index, { :format => "m" }
assert_equal 10, assigns['down_count']
assert_equal 11, assigns['down_count']
end
def test_mobile_create_action_creates_a_new_todo
@ -362,38 +362,127 @@ class TodosControllerTest < Test::Rails::TestCase
# link todo_1 and recurring_todo_1
recurring_todo_1 = RecurringTodo.find(1)
todo_1 = Todo.find(1)
todo_1.recurring_todo_id = recurring_todo_1.id
# update todo_1
assert todo_1.save
todo_1 = Todo.find_by_recurring_todo_id(1)
# mark todo_1 as complete by toggle_check
xhr :post, :toggle_check, :id => 1, :_source_view => 'todo'
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 weekly and set show_from 2 days befor due date
# this forces the next todo to be put in the tickler
# 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.recurring_period = 'weekly'
recurring_todo_1.every_day = 'smtwtfs'
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
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)
todo_1 = Todo.find_by_recurring_todo_id(1)
today = Time.now.utc.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
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?
assert_equal Time.utc(today.year, today.month+1, today.day), new_todo.show_from
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
end

View file

@ -53,7 +53,7 @@ class ContextTest < Test::Rails::TestCase
end
def test_delete_context_deletes_todos_within_it
assert_equal 6, @agenda.todos.count
assert_equal 7, @agenda.todos.count
agenda_todo_ids = @agenda.todos.collect{|t| t.id }
@agenda.destroy
agenda_todo_ids.each do |todo_id|
@ -62,11 +62,11 @@ class ContextTest < Test::Rails::TestCase
end
def test_not_done_todos
assert_equal 5, @agenda.not_done_todos.size
assert_equal 6, @agenda.not_done_todos.size
t = @agenda.not_done_todos[0]
t.complete!
t.save!
assert_equal 4, Context.find(@agenda.id).not_done_todos.size
assert_equal 5, Context.find(@agenda.id).not_done_todos.size
end
def test_done_todos

View file

@ -172,9 +172,9 @@ class ProjectTest < Test::Rails::TestCase
def test_not_done_todo_count
assert_equal 2, @timemachine.not_done_todo_count
assert_equal 3, @moremoney.not_done_todo_count
assert_equal 4, @moremoney.not_done_todo_count
@moremoney.todos[0].complete!
assert_equal 2, @moremoney.not_done_todo_count
assert_equal 3, @moremoney.not_done_todo_count
end
def test_default_context_name

View file

@ -174,6 +174,9 @@ class RecurringTodoTest < Test::Rails::TestCase
# same month, day after
due_date = @yearly.get_due_date(@monday) # june 9th
assert_equal Time.zone.local(2009,6,8), due_date # june 8th next year
# very overdue
due_date = @yearly.get_due_date(@monday+5.months-2.days) # november 7
assert_equal Time.zone.local(2009,6,8), due_date # june 8th next year
@yearly.recurrence_selector = 1
@yearly.every_other3 = 2 # second
@ -194,6 +197,15 @@ class RecurringTodoTest < Test::Rails::TestCase
assert_equal due_date1, due_date2
end
def test_last_sunday_of_march
@yearly.recurrence_selector = 1
@yearly.every_other2 = 3 # march
@yearly.every_other3 = 5 # last
@yearly.every_count = 0 # sunday
due_date = @yearly.get_due_date(Time.zone.local(2008,10,1)) # oct 1st
assert_equal Time.zone.local(2009,3,29), due_date # march 29th
end
def test_start_from_in_future
# every_day should return start_day if it is in the future
@every_day.start_from = @in_three_days