Start major refactoring of recurring_todos. Started with creating new recurring todos.

All current and new tests pass
This commit is contained in:
Reinier Balt 2014-01-27 16:42:54 +01:00
parent 8e13059df1
commit 78c07d52b7
26 changed files with 1218 additions and 32 deletions

View file

@ -62,6 +62,52 @@ class RecurringTodosControllerTest < ActionController::TestCase
assert_equal orig_todo_count+1, Todo.count
end
def test_new_recurring_todo_handles_attribs_outside_rec_todo
login_as(:admin_user)
# check new rec todo is not there
assert_nil RecurringTodo.where(:description => "new recurring pattern").first
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" => "31/08/2010",
"ends_on" => "ends_on_end_date",
"monthly_day_of_week" => "1",
"monthly_every_x_day" => "18",
"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"=>"10",
"recurring_target"=>"due_date",
"recurring_show_always" => "1",
"start_from"=>"18/08/2008",
"weekly_every_x_week"=>"1",
"weekly_return_monday"=>"m",
"yearly_day_of_week"=>"1",
"yearly_every_x_day"=>"8",
"yearly_every_xth_day"=>"1",
"yearly_month_of_year2"=>"8",
"yearly_month_of_year"=>"6",
"yearly_selector"=>"yearly_every_x_day"
},
"tag_list"=>"one, two, three, four", :format => :js
new_rec_todo = RecurringTodo.where(:description => "new recurring pattern").first
assert_not_nil new_rec_todo
end
def test_recurring_todo_toggle_check
# the test fixtures did add recurring_todos but not the corresponding todos,
# so we check complete and uncheck to force creation of a todo from the

View file

@ -0,0 +1,122 @@
require_relative '../../test_helper'
module RecurringTodos
class AbstractRecurringTodosBuilderTest < ActiveSupport::TestCase
fixtures :users
def setup
@admin = users(:admin_user)
end
def test_filter_attributes_should_throw_exception
attributes = {
'recurring_period' => "daily",
'description' => "test",
'tag_list' => "tag, this, that",
'context_name' => "my new context",
'daily_selector' => 'daily_every_work_day',
'target' => 'due_date',
'show_always' => true,
'start_from' => '01/01/01',
'ends_on' => 'no_end_date'
}
assert_raise(Exception, "should have exception since we are using abstract builder") do
builder = AbstractRecurringTodosBuilder.new(@admin, attributes)
end
end
def test_tags_should_be_filled_or_empty_string
# given attributes with filled tag_list
attributes = {
'recurring_period' => 'daily',
'daily_selector' => 'daily_every_work_day',
'tag_list' => "tag, this, that"
}
builder = RecurringTodosBuilder.new(@admin, attributes)
assert_equal "tag, this, that", builder.attributes[:tag_list]
# given attributes without tag_list
attributes = {
'recurring_period' => 'daily',
'daily_selector' => 'daily_every_work_day',
}
builder = RecurringTodosBuilder.new(@admin, attributes)
assert_equal "", builder.attributes[:tag_list]
# given attributes with nil tag_list
attributes = {
'recurring_period' => 'daily',
'daily_selector' => 'daily_every_work_day',
'tag_list' => nil
}
builder = RecurringTodosBuilder.new(@admin, attributes)
assert_equal "", builder.attributes[:tag_list]
# given attributes with empty tag_list ==> should be stripped
attributes = {
'recurring_period' => 'daily',
'daily_selector' => 'daily_every_work_day',
'tag_list' => " "
}
builder = RecurringTodosBuilder.new(@admin, attributes)
assert_equal "", builder.attributes[:tag_list]
end
def test_tags_should_be_saved
attributes = {
'recurring_period' => "daily",
'description' => "test",
'tag_list' => "tag, this, that",
'context_name' => "my new context",
'daily_selector' => 'daily_every_work_day',
'recurring_target' => 'show_from_date',
'show_always' => true,
'start_from' => '01/01/01',
'ends_on' => 'no_end_date'
}
builder = RecurringTodosBuilder.new(@admin, attributes)
assert builder.save, "it should be saved"
assert_equal "tag, that, this", builder.saved_recurring_todo.tag_list, "tags should be saved"
attributes['tag_list'] = '' # clear tag_list
builder = RecurringTodosBuilder.new(@admin, attributes)
assert !builder.tag_list.present?, "tag list should not be present"
assert builder.save, "it should be saved"
assert_equal "", builder.saved_recurring_todo.tag_list, "tag list should be empty"
end
def test_saved_should_raise_exception_on_validation_errors
attributes = {
'recurring_period' => "daily",
'description' => "test",
'tag_list' => "tag, this, that",
'context_name' => "my new context",
'daily_selector' => 'daily_every_work_day',
'recurring_target' => 'due_date',
'show_always' => true,
'start_from' => '01/01/01',
'ends_on' => 'no_end_date_error' # invalid end_on value
}
# creating builder should not raise exception
builder = RecurringTodosBuilder.new(@admin, attributes)
builder.build
assert !builder.recurring_todo.valid?, "model should have validation errors"
assert !builder.save, "should not be able to save because of validation errors"
assert_raise(Exception, "should have exception since there is no saved recurring todo"){ builder.saved_recurring_todo }
end
end
end

View file

@ -0,0 +1,46 @@
require_relative '../../test_helper'
module RecurringTodos
class AbstractRepeatPatternTest < ActiveSupport::TestCase
fixtures :users
class TestRepeatPattern < AbstractRepeatPattern
def valid_selector?(selector)
true
end
end
def setup
@admin = users(:admin_user)
end
def test_map_removes_mapped_key
attributes = { :source => "value"}
arp = AbstractRepeatPattern.new(@admin, attributes)
attributes = arp.map(attributes, :target, :source)
assert_equal "value", attributes[:target]
assert_nil attributes[:source]
assert !attributes.key?(:source)
end
def test_get_selector_removes_selector_from_hash
attributes = { :selector => "weekly" }
arp = TestRepeatPattern.new(@admin, attributes)
assert "weekly", arp.get_selector(:selector)
assert !arp.attributes.key?(:selector)
end
def test_get_selector_raises_exception_when_missing_selector
attributes = { }
arp = TestRepeatPattern.new(@admin, attributes)
assert_raise(Exception, "should raise exception when recurrence selector is missing"){ arp.get_selector(:selector) }
end
end
end

View file

@ -0,0 +1,35 @@
require_relative '../../test_helper'
module RecurringTodos
class DailyRecurringTodosBuilderTest < ActiveSupport::TestCase
fixtures :users
def setup
@admin = users(:admin_user)
end
def test_pattern_is_daily
object = RecurringTodosBuilder.new(@admin, { 'recurring_period' => 'daily', 'daily_selector' => 'daily_every_x_day' })
assert object.builder.is_a? DailyRecurringTodosBuilder
end
def test_filter_non_daily_attributes
attributes = {
'recurring_period' => 'daily',
'description' => 'a repeating todo', # generic
'daily_selector' => 'daily_every_x_day', # daily specific
'bla_bla' => 'go away' # irrelevant for daily
}
result = RecurringTodosBuilder.new(@admin, attributes).attributes
assert_nil result['bla_bla'], "bla_bla should be filtered"
assert_nil result[:bla_bla], "bla_bla should be filtered"
assert_equal false, result[:only_work_days], "daily attributes should be preserved"
assert_equal "a repeating todo", result[:description], "description should be preserved"
end
end
end

View file

@ -0,0 +1,58 @@
require_relative '../../test_helper'
module RecurringTodos
class DailyRepeatPatternTest < ActiveSupport::TestCase
fixtures :users
def setup
@admin = users(:admin_user)
end
def test_valid_selector
attributes = {
'recurring_period' => 'daily'
}
# should not raise
%w{daily_every_x_day daily_every_work_day}.each do |selector|
attributes['daily_selector'] = selector
DailyRepeatPattern.new(@admin, attributes)
end
# should raise
attributes = {
'recurring_period' => 'daily',
'daily_selector' => 'wrong value'
}
# should raise
assert_raise(Exception, "should have exception since daily_selector has wrong value"){ DailyRepeatPattern.new(@admin, attributes) }
end
def test_mapping_of_attributes
attributes = {
'recurring_period' => 'daily',
'description' => 'a repeating todo', # generic
'daily_selector' => 'daily_every_x_day', # daily specific --> mapped to only_work_days=false
'daily_every_x_days' => '5' # mapped to every_other1
}
pattern = DailyRepeatPattern.new(@admin, attributes)
assert_equal '5', pattern.mapped_attributes[:every_other1], "every_other1 should be set to daily_every_x_days"
assert_equal false, pattern.mapped_attributes[:only_work_days], "only_work_days should be set to false for daily_every_x_day"
attributes = {
'recurring_period' => 'daily',
'description' => 'a repeating todo', # generic
'daily_selector' => 'daily_every_work_day', # daily specific --> mapped to only_work_days=true
}
pattern = DailyRepeatPattern.new(@admin, attributes)
assert_equal true, pattern.mapped_attributes[:only_work_days]
end
end
end

View file

@ -0,0 +1,35 @@
require_relative '../../test_helper'
module RecurringTodos
class MonthlyRecurringTodosBuilderTest < ActiveSupport::TestCase
fixtures :users
def setup
@admin = users(:admin_user)
end
def test_pattern_is_monthly
object = RecurringTodosBuilder.new(@admin, { 'recurring_period' => 'monthly', 'monthly_selector' => 'monthly_every_x_day' })
assert object.builder.is_a?(MonthlyRecurringTodosBuilder), "Builder should be of type MonthlyRecurringTodosBuilder"
end
def test_filter_non_daily_attributes
attributes = {
'recurring_period' => 'monthly',
'description' => 'a repeating todo', # generic
'monthly_selector' => 'monthly_every_x_day', # monthly specific
'monthly_every_x_day' => 5, # should be preserved as :every_other1
'bla_bla' => 'go away' # irrelevant for daily
}
result = RecurringTodosBuilder.new(@admin, attributes).attributes
assert_nil result['bla_bla'], "bla_bla should be filtered"
assert_nil result[:bla_bla], "bla_bla should be filtered"
assert_equal 5, result[:every_other1], "should be preserved"
end
end
end

View file

@ -0,0 +1,74 @@
require_relative '../../test_helper'
module RecurringTodos
class MonthlyRepeatPatternTest < ActiveSupport::TestCase
fixtures :users
def setup
@admin = users(:admin_user)
end
def test_valid_selector
attributes = {
'recurring_period' => 'monthly'
}
# should not raise
%w{monthly_every_x_day monthly_every_xth_day}.each do |selector|
attributes['monthly_selector'] = selector
MonthlyRepeatPattern.new(@admin, attributes)
end
# should raise
attributes = {
'recurring_period' => 'monthly',
'monthly_selector' => 'wrong value'
}
# should raise
assert_raise(Exception, "should have exception since monthly_selector has wrong value"){ MonthlyRepeatPattern.new(@admin, attributes) }
end
def test_mapping_of_attributes
attributes = {
'recurring_period' => 'monthly',
'description' => 'a repeating todo', # generic
'monthly_selector' => 'monthly_every_x_day', # monthly specific
'monthly_every_x_day' => '5', # mapped to :every_other1
'monthly_every_xth_day' => '7', # mapped to :every_other3
'monthly_day_of_week' => 3, # mapped to :every_count
'monthly_every_x_month' => '10', # mapped to :every_other2
'monthly_every_x_month2' => '20' # not mapped
}
pattern = MonthlyRepeatPattern.new(@admin, attributes)
assert_equal 0, pattern.mapped_attributes[:recurrence_selector], "selector should be 0 for monthly_every_x_day"
assert_equal '5', pattern.mapped_attributes[:every_other1], "every_other1 should be set to monthly_every_x_days"
assert_equal '10', pattern.mapped_attributes[:every_other2], "every_other2 should be set to monthly_every_x_month when selector is monthly_every_x_day (=0)"
assert_equal '7', pattern.mapped_attributes[:every_other3], "every_other3 should be set to monthly_every_xth_day"
assert_equal 3, pattern.mapped_attributes[:every_count], "every_count should be set to monthly_day_of_week"
pattern.build_recurring_todo
assert pattern.every_x_day?, "every_x_day? should say true for selector monthly_every_x_day"
attributes = {
'recurring_period' => 'monthly',
'description' => 'a repeating todo', # generic
'monthly_selector' => 'monthly_every_xth_day', # monthly specific
'monthly_every_x_day' => '5', # mapped to :every_other1
'monthly_every_x_month' => '10', # not mapped
'monthly_every_x_month2' => '20' # mapped to :every_other2
}
pattern = MonthlyRepeatPattern.new(@admin, attributes)
assert_equal 1, pattern.mapped_attributes[:recurrence_selector], "selector should be 1 for monthly_every_xth_day"
assert_equal '20', pattern.mapped_attributes[:every_other2], "every_other2 should be set to monthly_every_x_month2 when selector is monthly_every_xth_day (=0)"
pattern.build_recurring_todo
assert pattern.every_xth_day?, "every_xth_day? should say true for selector monthly_every_xth_day"
end
end
end

View file

@ -0,0 +1,122 @@
require_relative '../../test_helper'
module RecurringTodos
class RecurringTodosBuilderTest < ActiveSupport::TestCase
fixtures :users
def setup
@admin = users(:admin_user)
end
def test_create_builder_needs_selector
assert_raise(Exception){ builder = RecurringTodosBuilder.new(@admin, {}) }
end
def test_create_builder_uses_selector
builder = RecurringTodosBuilder.new(@admin, {'recurring_period' => "daily", 'daily_selector' => 'daily_every_work_day'}).builder
assert builder.is_a?(DailyRecurringTodosBuilder)
builder = RecurringTodosBuilder.new(@admin, {'recurring_period' => "weekly"}).builder
assert builder.is_a?(WeeklyRecurringTodosBuilder)
builder = RecurringTodosBuilder.new(@admin, {'recurring_period' => "monthly", 'monthly_selector' => 'monthly_every_x_day'}).builder
assert builder.is_a?(MonthlyRecurringTodosBuilder)
builder = RecurringTodosBuilder.new(@admin, {'recurring_period' => "yearly", 'yearly_selector' => 'yearly_every_x_day'}).builder
assert builder.is_a?(YearlyRecurringTodosBuilder)
end
def test_dates_are_parsed
builder = RecurringTodosBuilder.new(@admin, {
'recurring_period' => "daily",
'daily_selector' => 'daily_every_work_day',
'start_from' => "01/01/01",
'end_date' => '05/05/05'
})
assert builder.attributes[:start_from].is_a?(ActiveSupport::TimeWithZone), "Dates should be parsed to ActiveSupport::TimeWithZone class"
assert builder.attributes[:end_date].is_a?(ActiveSupport::TimeWithZone), "Dates should be parsed to ActiveSupport::TimeWithZone class"
end
def test_exisisting_project_is_used
# test by project_name
builder = RecurringTodosBuilder.new(@admin, {
'recurring_period' => "daily",
'project_name' => @admin.projects.first.name,
'daily_selector' => 'daily_every_work_day'})
assert_equal @admin.projects.first, builder.project
# test by project_id
builder = RecurringTodosBuilder.new(@admin, {
'recurring_period' => "daily",
'daily_selector' => 'daily_every_work_day',
'project_id' => @admin.projects.first.id})
assert_equal @admin.projects.first, builder.project
end
def test_not_exisisting_project_is_created
builder = RecurringTodosBuilder.new(@admin, {
'recurring_period' => "daily",
'project_name' => "my new project",
'daily_selector' => 'daily_every_work_day',
'recurring_target' => 'due_date'})
assert_equal "my new project", builder.project.name, "project should exist"
assert !builder.project.persisted?, "new project should not be persisted before save"
builder.save
assert builder.project.persisted?, "new project should be persisted after save"
end
def test_exisisting_context_is_used
builder = RecurringTodosBuilder.new(@admin, {
'recurring_period' => "daily",
'context_name' => @admin.contexts.first.name,
'daily_selector' => 'daily_every_work_day'})
assert_equal @admin.contexts.first, builder.context
builder = RecurringTodosBuilder.new(@admin, {
'recurring_period' => "daily",
'daily_selector' => 'daily_every_work_day',
'context_id' => @admin.contexts.first.id})
assert_equal @admin.contexts.first, builder.context
end
def test_not_exisisting_context_is_created
builder = RecurringTodosBuilder.new(@admin, {
'recurring_period' => "daily",
'context_name' => "my new context",
'daily_selector' => 'daily_every_work_day',
'recurring_target' => 'due_date'})
assert_equal "my new context", builder.context.name, "context should exist"
assert !builder.context.persisted?, "new context should not be persisted before save"
builder.save
assert builder.context.persisted?, "new context should be persisted after save"
end
def test_project_is_optional
builder = RecurringTodosBuilder.new(@admin, {
'recurring_period' => "daily",
'description' => "test",
'context_name' => "my new context",
'daily_selector' => 'daily_every_work_day',
'recurring_target' => 'show_from_date',
'show_always' => true,
'start_from' => '01/01/01',
'ends_on' => 'no_end_date'})
assert_nil builder.project, "project should not exist"
builder.save
assert_nil builder.saved_recurring_todo.project
end
end
end

View file

@ -0,0 +1,35 @@
require_relative '../../test_helper'
module RecurringTodos
class WeeklyRecurringTodosBuilderTest < ActiveSupport::TestCase
fixtures :users
def setup
@admin = users(:admin_user)
end
def test_pattern_is_weekly
object = RecurringTodosBuilder.new(@admin, { 'recurring_period' => 'weekly' })
assert object.builder.is_a? WeeklyRecurringTodosBuilder
end
def test_filter_non_daily_attributes
attributes = {
'recurring_period' => 'weekly',
'description' => 'a repeating todo', # generic
'weekly_return_monday' => 'm', # weekly specific
'bla_bla' => 'go away' # irrelevant
}
result = RecurringTodosBuilder.new(@admin, attributes).attributes
assert_nil result['bla_bla'], "bla_bla should be filtered"
assert_nil result[:bla_bla], "bla_bla should be filtered"
assert_equal ' m ', result[:every_day], "weekly attributes should be preserved"
assert_equal "a repeating todo", result[:description], "description should be preserved"
end
end
end

View file

@ -0,0 +1,52 @@
require_relative '../../test_helper'
module RecurringTodos
class WeeklyRepeatPatternTest < ActiveSupport::TestCase
fixtures :users
def setup
@admin = users(:admin_user)
end
def test_mapping_of_attributes
attributes = {
'recurring_period' => 'weekly',
'description' => 'a repeating todo', # generic
'weekly_every_x_week' => '5', # mapped to every_other1
'weekly_return_monday' => 'm'
}
pattern = WeeklyRepeatPattern.new(@admin, attributes)
assert_equal '5', pattern.mapped_attributes[:every_other1], "every_other1 should be set to weekly_every_x_week"
assert_equal ' m ', pattern.mapped_attributes[:every_day], "weekly_return_<weekday> should be mapped to :every_day in format 'smtwtfs'"
end
def test_map_day
attributes = {
'recurring_period' => 'weekly',
'description' => 'a repeating todo', # generic
'weekly_every_x_week' => '5' # mapped to every_other1
}
pattern = WeeklyRepeatPattern.new(@admin, attributes)
assert_equal ' ', pattern.mapped_attributes[:every_day], "all days should be empty in :every_day"
# add all days
{ sunday: 's', monday: 'm', tuesday: 't', wednesday: 'w', thursday: 't', friday: 'f', saturday: 's' }.each do |day, short|
attributes["weekly_return_#{day}"] = short
end
pattern = WeeklyRepeatPattern.new(@admin, attributes)
assert_equal 'smtwtfs', pattern.mapped_attributes[:every_day], "all days should be filled in :every_day"
# remove wednesday
attributes = attributes.except('weekly_return_wednesday')
pattern = WeeklyRepeatPattern.new(@admin, attributes)
assert_equal 'smt tfs', pattern.mapped_attributes[:every_day], "only wednesday should be empty in :every_day"
end
end
end

View file

@ -0,0 +1,36 @@
require_relative '../../test_helper'
module RecurringTodos
class YearlyRecurringTodosBuilderTest < ActiveSupport::TestCase
fixtures :users
def setup
@admin = users(:admin_user)
end
def test_pattern_is_yearly
object = RecurringTodosBuilder.new(@admin, { 'recurring_period' => 'yearly', 'yearly_selector' => 'yearly_every_x_day' })
assert object.builder.is_a? YearlyRecurringTodosBuilder
end
def test_filter_non_daily_attributes
attributes = {
'recurring_period' => 'yearly',
'description' => 'a repeating todo', # generic
'yearly_selector' => 'yearly_every_x_day', # daily specific
'yearly_month_of_year' => '1', # mapped to evert_other2 because yearly_selector is yearly_every_x_day
'bla_bla' => 'go away' # irrelevant for daily
}
result = RecurringTodosBuilder.new(@admin, attributes).attributes
assert_nil result['bla_bla'], "bla_bla should be filtered"
assert_nil result[:bla_bla], "bla_bla should be filtered"
assert_equal '1', result[:every_other2], "yearly attributes should be preserved"
assert_equal "a repeating todo", result[:description], "description should be preserved"
end
end
end

View file

@ -0,0 +1,66 @@
require_relative '../../test_helper'
module RecurringTodos
class YearlyRepeatPatternTest < ActiveSupport::TestCase
fixtures :users
def setup
@admin = users(:admin_user)
end
def test_valid_selector
attributes = {
'recurring_period' => 'yearly'
}
# should not raise
%w{yearly_every_x_day yearly_every_xth_day}.each do |selector|
attributes['yearly_selector'] = selector
YearlyRepeatPattern.new(@admin, attributes)
end
# should raise
attributes = {
'recurring_period' => 'yearly',
'yearly_selector' => 'wrong value'
}
# should raise
assert_raise(Exception, "should have exception since yearly_selector has wrong value"){ YearlyRepeatPattern.new(@admin, attributes) }
end
def test_mapping_of_attributes
attributes = {
'recurring_period' => 'yearly',
'description' => 'a repeating todo', # generic
'yearly_selector' => 'yearly_every_x_day', # yearly specific
'yearly_every_x_day' => '5', # mapped to every_other1
'yearly_every_xth_day' => '7', # mapped to every_other3
'yearly_day_of_week' => '3', # mapped to every_count
'yearly_month_of_year' => '1', # mapped to evert_other2 because yearly_selector is yearly_every_x_day
'yearly_month_of_year2' => '2' # ignored because yearly_selector is yearly_every_x_day
}
pattern = YearlyRepeatPattern.new(@admin, attributes)
assert_equal '5', pattern.mapped_attributes[:every_other1], "every_other1 should be set to yearly_every_x_day"
assert_equal '1', pattern.mapped_attributes[:every_other2], "every_other2 should be set to yearly_month_of_year because selector is yearly_every_x_day"
assert_equal '7', pattern.mapped_attributes[:every_other3], "every_other3 should be set to yearly_every_xth_day"
assert_equal '3', pattern.mapped_attributes[:every_count], "every_count should be set to yearly_day_of_week"
attributes = {
'recurring_period' => 'yearly',
'description' => 'a repeating todo', # generic
'yearly_selector' => 'yearly_every_xth_day', # daily specific --> mapped to only_work_days=false
'yearly_month_of_year' => '1', # ignored because yearly_selector is yearly_every_xth_day
'yearly_month_of_year2' => '2' # mapped to evert_other2 because yearly_selector is yearly_every_xth_day
}
pattern = YearlyRepeatPattern.new(@admin, attributes)
assert_equal '2', pattern.mapped_attributes[:every_other2], "every_other2 should be set to yearly_month_of_year2 because selector is yearly_every_xth_day"
end
end
end