mirror of
https://github.com/TracksApp/tracks.git
synced 2026-02-17 20:58:09 +01:00
move tests to new directory
This commit is contained in:
parent
65859807ea
commit
0bc9b0397a
42 changed files with 23 additions and 32 deletions
0
test/models/.gitkeep
Normal file
0
test/models/.gitkeep
Normal file
100
test/models/context_test.rb
Normal file
100
test/models/context_test.rb
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class ContextTest < ActiveSupport::TestCase
|
||||
fixtures :contexts, :todos, :recurring_todos, :users, :preferences
|
||||
|
||||
def setup
|
||||
@agenda = contexts(:agenda)
|
||||
@email = contexts(:email)
|
||||
@library = contexts(:library)
|
||||
end
|
||||
|
||||
def test_uses_acts_as_list
|
||||
# only check that acts_as_list is present in the model
|
||||
assert @agenda.respond_to?(:move_to_bottom)
|
||||
end
|
||||
|
||||
def test_validate_presence_of_name
|
||||
@agenda.name = ""
|
||||
assert !@agenda.save
|
||||
assert_equal 1, @agenda.errors.count
|
||||
assert_equal "context must have a name", @agenda.errors[:name][0]
|
||||
end
|
||||
|
||||
def test_validate_name_is_less_than_256
|
||||
@agenda.name = generate_random_string(256)
|
||||
assert !@agenda.save
|
||||
assert_equal 1, @agenda.errors.count
|
||||
assert_equal "context name must be less than 256 characters", @agenda.errors[:name][0]
|
||||
end
|
||||
|
||||
def test_validate_name_is_unique
|
||||
newcontext = Context.new
|
||||
newcontext.name = contexts(:agenda).name
|
||||
newcontext.user_id = contexts(:agenda).user_id
|
||||
assert !newcontext.save
|
||||
assert_equal 1, newcontext.errors.count
|
||||
assert_equal "already exists", newcontext.errors[:name][0]
|
||||
end
|
||||
|
||||
def test_delete_context_deletes_todos_within_it
|
||||
assert_equal 7, @agenda.todos.count
|
||||
agenda_todo_ids = @agenda.todos.collect{|t| t.id }
|
||||
@agenda.destroy
|
||||
agenda_todo_ids.each do |todo_id|
|
||||
assert !Todo.exists?(todo_id)
|
||||
end
|
||||
end
|
||||
|
||||
def test_to_param_returns_id
|
||||
assert_equal '1', @agenda.to_param
|
||||
end
|
||||
|
||||
def test_title_reader_returns_name
|
||||
assert_equal @agenda.name, @agenda.title
|
||||
end
|
||||
|
||||
def test_null_object
|
||||
c = Context.null_object
|
||||
assert c.nil?
|
||||
assert_nil c.id
|
||||
assert_equal '', c.name
|
||||
end
|
||||
|
||||
def test_new_record_before_save
|
||||
assert !@agenda.new_record_before_save?, "existing records should not be new_record"
|
||||
c = Context.where(:name => "I do not exist").first_or_create
|
||||
assert c.new_record_before_save?, "newly created record should be new_record"
|
||||
end
|
||||
|
||||
def test_hide_context
|
||||
assert @agenda.active?
|
||||
@agenda.hide!
|
||||
assert @agenda.hidden?
|
||||
end
|
||||
|
||||
def test_closing_context_guarded_for_active_todos
|
||||
assert @agenda.active?
|
||||
assert AASM::InvalidTransition do
|
||||
@agenda.close!
|
||||
end
|
||||
|
||||
@agenda.todos.active.each {|t| t.complete! }
|
||||
@agenda.close!
|
||||
assert @agenda.closed?
|
||||
end
|
||||
|
||||
def test_activating_closed_context
|
||||
# given a context @agenda that is closed
|
||||
@agenda.todos.active.each {|t| t.complete! }
|
||||
@agenda.close!
|
||||
assert @agenda.closed?
|
||||
|
||||
# when I activate @agenda
|
||||
@agenda.activate!
|
||||
|
||||
# then @agenda should have an active state
|
||||
assert @agenda.active?
|
||||
end
|
||||
|
||||
end
|
||||
46
test/models/is_taggable_test.rb
Normal file
46
test/models/is_taggable_test.rb
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class IsTaggableTest < ActiveSupport::TestCase
|
||||
fixtures :todos, :recurring_todos
|
||||
|
||||
def test_models_are_taggable
|
||||
assert Todo.first.respond_to?(:tag_list)
|
||||
assert RecurringTodo.first.respond_to?(:tag_list)
|
||||
end
|
||||
|
||||
def test_test_to_s
|
||||
t = Todo.create(:description => "test", :context => Context.first)
|
||||
t.tag_list = "one, two, three"
|
||||
|
||||
# tags will be sorted alphabetical
|
||||
assert_equal "one, three, two", t.tag_list
|
||||
assert_equal "one, three, two", t.tags.to_s
|
||||
end
|
||||
|
||||
def test_getting_all_tags_except_starred
|
||||
t = Todo.create(:description => "test", :context => Context.first)
|
||||
t.tag_list = "one, two, three"
|
||||
t.toggle_star!
|
||||
|
||||
assert_equal "one, starred, three, two", t.tag_list
|
||||
assert_equal "one, three, two", t.tags.all_except_starred.map(&:name).sort.join(", ")
|
||||
end
|
||||
|
||||
def test_editing_tags
|
||||
t = Todo.create(:description => "test", :context => Context.first)
|
||||
t.tag_list = "a, b, c"
|
||||
|
||||
assert_equal 3, t.tags.count
|
||||
|
||||
t.tag_with "a, b"
|
||||
|
||||
assert_equal "a, b", t.tag_list, "should remove tag c"
|
||||
|
||||
t.tag_with "a, b, c, d"
|
||||
assert_equal "a, b, c, d", t.tag_list, "should add c and d"
|
||||
|
||||
t.tag_with "a, b, e, f"
|
||||
assert_equal "a, b, e, f", t.tag_list, "should add e and f and remove c and d"
|
||||
end
|
||||
|
||||
end
|
||||
14
test/models/notes_test.rb
Normal file
14
test/models/notes_test.rb
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class NotesTest < ActiveSupport::TestCase
|
||||
fixtures :notes
|
||||
|
||||
def setup
|
||||
@notes = Note.find(1)
|
||||
end
|
||||
|
||||
# Replace this with your real tests.
|
||||
def test_truth
|
||||
assert_kind_of Note, @notes
|
||||
end
|
||||
end
|
||||
84
test/models/pie_chart_data_test.rb
Normal file
84
test/models/pie_chart_data_test.rb
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../minimal_test_helper')
|
||||
require 'app/models/stats/pie_chart_data'
|
||||
require 'active_support/core_ext/string'
|
||||
|
||||
class Stats::PieChartDataTest < Test::Unit::TestCase
|
||||
|
||||
def setup
|
||||
xx = { :stats => { :other_actions_label => '(other)' } }
|
||||
I18n.backend.store_translations(:xx, xx)
|
||||
I18n.locale = :xx
|
||||
end
|
||||
|
||||
def test_with_0_items
|
||||
data = Stats::PieChartData.new([], 'a chart', 50)
|
||||
|
||||
assert_equal [], data.values
|
||||
assert_equal [], data.labels
|
||||
assert_equal [], data.ids
|
||||
end
|
||||
|
||||
def test_with_less_than_10_items
|
||||
items = [
|
||||
{'id' => 1, 'name' => 'one', 'total' => 11},
|
||||
{'id' => 2, 'name' => 'two', 'total' => 4},
|
||||
{'id' => 3, 'name' => 'three', 'total' => 8},
|
||||
{'id' => 4, 'name' => 'four', 'total' => 13},
|
||||
{'id' => 5, 'name' => 'five', 'total' => 20},
|
||||
{'id' => 6, 'name' => 'six', 'total' => 17},
|
||||
{'id' => 7, 'name' => 'seven', 'total' => 5},
|
||||
{'id' => 8, 'name' => 'eight', 'total' => 1},
|
||||
{'id' => 9, 'name' => 'nine', 'total' => 6}
|
||||
]
|
||||
|
||||
data = Stats::PieChartData.new(items, 'a chart', 50)
|
||||
|
||||
assert_equal [12, 4, 9, 15, 23, 20, 5, 1, 7], data.values
|
||||
assert_equal ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"], data.labels
|
||||
assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9], data.ids
|
||||
end
|
||||
|
||||
def test_with_exactly_10_items
|
||||
items = [
|
||||
{'id' => 1, 'name' => 'one', 'total' => 11},
|
||||
{'id' => 2, 'name' => 'two', 'total' => 4},
|
||||
{'id' => 3, 'name' => 'three', 'total' => 8},
|
||||
{'id' => 4, 'name' => 'four', 'total' => 13},
|
||||
{'id' => 5, 'name' => 'five', 'total' => 20},
|
||||
{'id' => 6, 'name' => 'six', 'total' => 17},
|
||||
{'id' => 7, 'name' => 'seven', 'total' => 5},
|
||||
{'id' => 8, 'name' => 'eight', 'total' => 1},
|
||||
{'id' => 9, 'name' => 'nine', 'total' => 6},
|
||||
{'id' => 10, 'name' => 'ten', 'total' => 19}
|
||||
]
|
||||
|
||||
data = Stats::PieChartData.new(items, 'a chart', 50)
|
||||
|
||||
assert_equal [10, 3, 7, 12, 19, 16, 4, 0, 5, 18], data.values
|
||||
assert_equal ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"], data.labels
|
||||
assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], data.ids
|
||||
end
|
||||
|
||||
def test_with_more_than_10_items
|
||||
items = [
|
||||
{'id' => 1, 'name' => 'one', 'total' => 11},
|
||||
{'id' => 2, 'name' => 'two', 'total' => 4},
|
||||
{'id' => 3, 'name' => 'three', 'total' => 8},
|
||||
{'id' => 4, 'name' => 'four', 'total' => 13},
|
||||
{'id' => 5, 'name' => 'five', 'total' => 20},
|
||||
{'id' => 6, 'name' => 'six', 'total' => 17},
|
||||
{'id' => 7, 'name' => 'seven', 'total' => 5},
|
||||
{'id' => 8, 'name' => 'eight', 'total' => 1},
|
||||
{'id' => 9, 'name' => 'nine', 'total' => 6},
|
||||
{'id' => 10, 'name' => 'ten', 'total' => 19},
|
||||
{'id' => 11, 'name' => 'eleven', 'total' => 14}
|
||||
]
|
||||
|
||||
data = Stats::PieChartData.new(items, 'a chart', 50)
|
||||
|
||||
assert_equal [9, 3, 6, 11, 16, 14, 4, 0, 5, 27], data.values
|
||||
assert_equal ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "(other)"], data.labels
|
||||
assert_equal [1, 2, 3, 4, 5, 6, 7, 8, 9, -1], data.ids
|
||||
end
|
||||
|
||||
end
|
||||
34
test/models/preference_test.rb
Normal file
34
test/models/preference_test.rb
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class PreferenceTest < ActiveSupport::TestCase
|
||||
fixtures :users, :preferences
|
||||
|
||||
def setup
|
||||
assert_equal "test", ENV['RAILS_ENV']
|
||||
assert_equal "change-me", Tracks::Config.salt
|
||||
@admin_user = User.find(1)
|
||||
@other_user = User.find(2)
|
||||
end
|
||||
|
||||
def test_time_zone
|
||||
assert_equal 'London', @admin_user.preference.time_zone
|
||||
end
|
||||
|
||||
def test_show_project_on_todo_done
|
||||
assert @other_user.preference.show_project_on_todo_done
|
||||
assert !@admin_user.preference.show_project_on_todo_done
|
||||
end
|
||||
|
||||
def test_parse_date
|
||||
assert_equal @admin_user.at_midnight(Date.new(2007, 5, 20)).to_s, @admin_user.preference.parse_date('20/5/2007').to_s
|
||||
end
|
||||
|
||||
def test_parse_date_returns_nil_if_string_is_empty
|
||||
assert_nil @admin_user.preference.parse_date('')
|
||||
end
|
||||
|
||||
def test_parse_date_returns_nil_if_string_is_nil
|
||||
assert_nil @admin_user.preference.parse_date(nil)
|
||||
end
|
||||
|
||||
end
|
||||
22
test/models/project_from_todo_test.rb
Normal file
22
test/models/project_from_todo_test.rb
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
require_relative '../test_helper'
|
||||
require_relative '../../lib/project_from_todo'
|
||||
|
||||
class ProjectFromTodoTest < ActiveSupport::TestCase
|
||||
fixtures :todos
|
||||
|
||||
def test_create_project_from_valid_todo
|
||||
todo = todos(:upgrade_rails)
|
||||
project = ProjectFromTodo.new(todo).create
|
||||
assert_equal project.name, todo.description
|
||||
assert_equal project.description, todo.notes
|
||||
assert_equal project.default_context, todo.context
|
||||
end
|
||||
|
||||
def test_invalid_project_from_invalid_todo
|
||||
todo = todos(:upgrade_rails)
|
||||
todo.description = ""
|
||||
project = ProjectFromTodo.new(todo).create
|
||||
assert_not_nil project
|
||||
assert_equal false, project.valid?
|
||||
end
|
||||
end
|
||||
241
test/models/project_test.rb
Normal file
241
test/models/project_test.rb
Normal file
|
|
@ -0,0 +1,241 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class ProjectTest < ActiveSupport::TestCase
|
||||
fixtures :projects, :contexts, :todos, :recurring_todos, :users, :preferences
|
||||
|
||||
def setup
|
||||
@timemachine = projects(:timemachine)
|
||||
@moremoney = projects(:moremoney)
|
||||
end
|
||||
|
||||
# associations
|
||||
|
||||
def test_has_default_context
|
||||
assert !@timemachine.default_context.nil?
|
||||
assert @timemachine.default_context.name == contexts(:lab).name
|
||||
|
||||
p = Project.new
|
||||
assert_equal '', p.default_context.name
|
||||
p.default_context = contexts(:agenda)
|
||||
assert_equal 'agenda', p.default_context.name
|
||||
end
|
||||
|
||||
# validations
|
||||
|
||||
def test_validate_presence_of_name
|
||||
@timemachine.name = ""
|
||||
assert !@timemachine.save
|
||||
assert_equal 1, @timemachine.errors.count
|
||||
assert_equal "project must have a name", @timemachine.errors[:name][0]
|
||||
end
|
||||
|
||||
def test_validate_name_is_less_than_256
|
||||
@timemachine.name = generate_random_string(256)
|
||||
assert !@timemachine.save
|
||||
assert_equal 1, @timemachine.errors.count
|
||||
assert_equal "project name must be less than 256 characters", @timemachine.errors[:name][0]
|
||||
end
|
||||
|
||||
def test_validate_name_is_unique
|
||||
newproj = Project.new
|
||||
newproj.name = projects(:timemachine).name
|
||||
newproj.user_id = projects(:timemachine).user_id
|
||||
assert !newproj.save
|
||||
assert_equal 1, newproj.errors.count
|
||||
assert_equal "already exists", newproj.errors[:name][0]
|
||||
end
|
||||
|
||||
# state machine
|
||||
|
||||
def test_project_initial_state_is_active
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
assert @timemachine.active?
|
||||
end
|
||||
|
||||
def test_hide_project
|
||||
@timemachine.hide!
|
||||
assert_equal :hidden, @timemachine.aasm_current_state
|
||||
assert @timemachine.hidden?
|
||||
end
|
||||
|
||||
def test_activate_project
|
||||
@timemachine.activate!
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
assert @timemachine.active?
|
||||
end
|
||||
|
||||
def test_transition_to_another_state
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
@timemachine.transition_to(:hidden)
|
||||
assert_equal :hidden, @timemachine.aasm_current_state
|
||||
@timemachine.transition_to(:completed)
|
||||
assert_equal :completed, @timemachine.aasm_current_state
|
||||
@timemachine.transition_to(:active)
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
end
|
||||
|
||||
def test_transition_to_same_state
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
@timemachine.transition_to(:active)
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
end
|
||||
|
||||
# other tests
|
||||
|
||||
def test_review_project
|
||||
assert_nil @timemachine.last_reviewed
|
||||
assert @timemachine.needs_review?(nil)
|
||||
end
|
||||
|
||||
def test_review_completedprojects
|
||||
@timemachine.complete!
|
||||
assert !@timemachine.needs_review?(nil)
|
||||
end
|
||||
|
||||
def test_complete_project
|
||||
assert_nil @timemachine.completed_at
|
||||
@timemachine.complete!
|
||||
assert_equal :completed, @timemachine.aasm_current_state
|
||||
assert @timemachine.completed?
|
||||
assert_not_nil @timemachine.completed_at, "completed_at not expected to be nil"
|
||||
assert_in_delta Time.now, @timemachine.completed_at, 1
|
||||
end
|
||||
|
||||
def test_delete_project_deletes_todos_within_it
|
||||
assert_equal 3, @timemachine.todos.count
|
||||
timemachine_todo_ids = @timemachine.todos.map{ |t| t.id }
|
||||
@timemachine.destroy
|
||||
timemachine_todo_ids.each do |t_id|
|
||||
assert !Todo.exists?(t_id)
|
||||
end
|
||||
end
|
||||
|
||||
def test_deferred_todos
|
||||
assert_equal 1, @timemachine.todos.deferred.size
|
||||
t = @timemachine.todos.not_completed[0]
|
||||
t.show_from = 1.days.from_now.utc
|
||||
t.save!
|
||||
assert_equal 2, Project.find(@timemachine.id).todos.deferred.size
|
||||
end
|
||||
|
||||
def test_to_param_returns_id
|
||||
assert_equal '1', @timemachine.to_param
|
||||
end
|
||||
|
||||
def test_null_object
|
||||
p = Project.null_object
|
||||
assert !p.hidden?
|
||||
assert p.nil?
|
||||
assert_nil p.id
|
||||
assert_equal "", p.name
|
||||
end
|
||||
|
||||
def test_name_removes_extra_spaces
|
||||
newproj = Project.new
|
||||
newproj.name = "These Words Have Proximity Issues "
|
||||
assert newproj.save
|
||||
assert_equal 0, newproj.errors.count
|
||||
assert_equal "These Words Have Proximity Issues", newproj.name
|
||||
|
||||
# and on update...
|
||||
@timemachine.name = " a time machine needs lots of spaaaaaaace "
|
||||
assert @timemachine.save
|
||||
assert_equal "a time machine needs lots of spaaaaaaace", @timemachine.name
|
||||
end
|
||||
|
||||
def test_deferred_todo_count
|
||||
assert_equal 1, @timemachine.todos.deferred.count
|
||||
assert_equal 0, @moremoney.todos.deferred.count
|
||||
|
||||
first_todo = @moremoney.todos[0]
|
||||
first_todo.show_from = Time.zone.now + 1.week
|
||||
first_todo.save!
|
||||
assert_equal :deferred, @moremoney.todos[0].aasm_current_state
|
||||
|
||||
assert_equal 1, @moremoney.todos.deferred.count
|
||||
end
|
||||
|
||||
def test_done_todo_count
|
||||
assert_equal 0, @timemachine.todos.completed.count
|
||||
assert_equal 0, @moremoney.todos.completed.count
|
||||
@moremoney.todos[0].complete!
|
||||
assert_equal 1, @moremoney.todos.completed.count
|
||||
end
|
||||
|
||||
def test_not_done_todo_count
|
||||
assert_equal 3, @timemachine.todos.not_completed.count
|
||||
assert_equal 4, @moremoney.todos.not_completed.count
|
||||
@moremoney.todos[0].complete!
|
||||
assert_equal 3, @moremoney.todos.not_completed.count
|
||||
end
|
||||
|
||||
def test_new_record_before_save
|
||||
assert !@timemachine.new_record_before_save?, "existing records should not be new_record"
|
||||
p = Project.where(:name => "I do not exist").first_or_create
|
||||
assert p.new_record_before_save?, "newly created record should be new_record"
|
||||
end
|
||||
|
||||
def test_shortened_name
|
||||
s = "project"*7 # len=49
|
||||
p = users(:admin_user).projects.create(:name => s)
|
||||
assert_equal 49, p.name.length
|
||||
assert_equal 40, p.shortened_name.length
|
||||
assert_equal "project"*5+"pr...", p.shortened_name
|
||||
|
||||
assert p.shortened_name.html_safe?
|
||||
end
|
||||
|
||||
def test_note_count
|
||||
p = users(:admin_user).projects.first
|
||||
assert_not_nil p
|
||||
|
||||
assert_equal 2, p.note_count
|
||||
|
||||
p.notes.create(:user_id => p.user_id, :body => "new note")
|
||||
|
||||
assert_equal 3, p.note_count
|
||||
end
|
||||
|
||||
def test_project_blocked
|
||||
p = users(:admin_user).projects.first
|
||||
todo_in_other_project = users(:admin_user).projects.last.todos.first
|
||||
|
||||
assert !p.blocked?, "first project should not be blocked"
|
||||
|
||||
p.complete!
|
||||
assert !p.blocked?, "completed projects should not be blocked"
|
||||
|
||||
p.activate!
|
||||
p.todos.each{|t| t.show_from = 2.weeks.from_now; t.save! }
|
||||
assert p.blocked?, "projects with deferred todos should be blocked"
|
||||
end
|
||||
|
||||
def test_project_stalled
|
||||
p = users(:admin_user).projects.first
|
||||
|
||||
p.hide!
|
||||
assert !p.stalled?, "hidden projects are not stalled"
|
||||
|
||||
p.complete!
|
||||
assert !p.stalled?, "completed projects are not stalled"
|
||||
|
||||
p.activate!
|
||||
p.todos.each{|t| t.complete!}
|
||||
assert p.todos.reload.active.empty?, "project should not have active todos"
|
||||
assert p.todos.reload.deferred_or_blocked.empty?, "there should not be deferred or blocked todos"
|
||||
assert p.reload.stalled?, "project should be stalled"
|
||||
end
|
||||
|
||||
def test_age_in_days
|
||||
p1 = users(:admin_user).projects.create!(:name => "test1")
|
||||
assert_equal 1, p1.age_in_days, "newly created project has age or one day"
|
||||
|
||||
p2 = users(:admin_user).projects.create!(:name => "test7")
|
||||
p2.created_at = 1.week.ago
|
||||
p2.save!
|
||||
|
||||
p2.reload
|
||||
assert_equal 8, p2.age_in_days
|
||||
end
|
||||
|
||||
end
|
||||
356
test/models/recurring_todo_test.rb
Normal file
356
test/models/recurring_todo_test.rb
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class RecurringTodoTest < ActiveSupport::TestCase
|
||||
|
||||
def setup
|
||||
@every_day = recurring_todos(:call_bill_gates_every_day)
|
||||
@every_workday = recurring_todos(:call_bill_gates_every_workday)
|
||||
@weekly_every_day = recurring_todos(:call_bill_gates_every_week)
|
||||
@every_week = @weekly_every_day
|
||||
@monthly_every_last_friday = recurring_todos(:check_with_bill_every_last_friday_of_month)
|
||||
@every_month = @monthly_every_last_friday
|
||||
@yearly = recurring_todos(:birthday_reinier)
|
||||
|
||||
@today = Time.now.utc
|
||||
@tomorrow = @today + 1.day
|
||||
@in_three_days = @today + 3.days
|
||||
@in_four_days = @in_three_days + 1.day # need a day after start_from
|
||||
|
||||
@friday = Time.zone.local(2008,6,6)
|
||||
@saturday = Time.zone.local(2008,6,7)
|
||||
@sunday = Time.zone.local(2008,6,8) # june 8, 2008 was a sunday
|
||||
@monday = Time.zone.local(2008,6,9)
|
||||
@tuesday = Time.zone.local(2008,6,10)
|
||||
@wednesday = Time.zone.local(2008,6,11)
|
||||
@thursday = Time.zone.local(2008,6,12)
|
||||
end
|
||||
|
||||
def test_pattern_text
|
||||
assert_equal "every day", @every_day.recurrence_pattern
|
||||
assert_equal "on work days", @every_workday.recurrence_pattern
|
||||
assert_equal "every last friday of every 2 months", @monthly_every_last_friday.recurrence_pattern
|
||||
assert_equal "every year on June 08", @yearly.recurrence_pattern
|
||||
end
|
||||
|
||||
def test_daily_every_day
|
||||
# every_day should return todays date if there was no previous date
|
||||
due_date = @every_day.get_due_date(nil)
|
||||
# use only day-month-year compare, because milisec / secs could be different
|
||||
assert_equal_dmy @today, due_date
|
||||
|
||||
# when the last todo was completed today, the next todo is due tomorrow
|
||||
due_date =@every_day.get_due_date(@today)
|
||||
assert_equal @tomorrow, due_date
|
||||
|
||||
# do something every 14 days
|
||||
@every_day.every_other1=14
|
||||
due_date = @every_day.get_due_date(@today)
|
||||
assert_equal @today+14.days, due_date
|
||||
end
|
||||
|
||||
def test_daily_work_days
|
||||
assert_equal @monday, @every_workday.get_due_date(@friday)
|
||||
assert_equal @monday, @every_workday.get_due_date(@saturday)
|
||||
assert_equal @monday, @every_workday.get_due_date(@sunday)
|
||||
assert_equal @tuesday, @every_workday.get_due_date(@monday)
|
||||
end
|
||||
|
||||
def test_show_from_date
|
||||
# assume that target due_date works fine, i.e. don't do the same tests over
|
||||
|
||||
@every_day.target='show_from_date'
|
||||
# when recurrence is targeted on show_from, due date shoult remain nil
|
||||
assert_equal nil, @every_day.get_due_date(nil)
|
||||
assert_equal nil, @every_day.get_due_date(@today-3.days)
|
||||
|
||||
# check show from get the next day
|
||||
assert_equal_dmy @today, @every_day.get_show_from_date(@today-1.days)
|
||||
assert_equal @today+1.day, @every_day.get_show_from_date(@today)
|
||||
|
||||
@every_day.target='due_date'
|
||||
# when target on due_date, show_from is relative to due date unless show_always is true
|
||||
@every_day.show_always = true
|
||||
assert_equal nil, @every_day.get_show_from_date(@today-1.days)
|
||||
|
||||
@every_day.show_always = false
|
||||
@every_day.show_from_delta=10
|
||||
assert_equal_dmy @today, @every_day.get_show_from_date(@today+9.days) #today+1+9-10
|
||||
|
||||
# when show_from is 0, show_from is the same day it's due
|
||||
@every_day.show_from_delta=0
|
||||
assert_equal @every_day.get_due_date(@today+9.days), @every_day.get_show_from_date(@today+9.days)
|
||||
|
||||
# when show_from is nil, show always (happend in tests)
|
||||
@every_day.show_from_delta=nil
|
||||
assert_equal nil, @every_day.get_show_from_date(@today+9.days)
|
||||
|
||||
# TODO: show_from has no use case for daily pattern. Need to test on
|
||||
# weekly/monthly/yearly
|
||||
end
|
||||
|
||||
def test_end_date_on_recurring_todo
|
||||
assert_equal true, @every_day.continues_recurring?(@in_three_days)
|
||||
assert_equal true, @every_day.continues_recurring?(@in_four_days)
|
||||
@every_day.end_date = @in_four_days
|
||||
@every_day.ends_on = 'ends_on_end_date'
|
||||
assert_equal false, @every_day.continues_recurring?(@in_four_days)
|
||||
end
|
||||
|
||||
def test_weekly_every_day_setters
|
||||
@weekly_every_day.every_day = ' '
|
||||
|
||||
@weekly_every_day.weekly_return_sunday=('s')
|
||||
assert_equal 's ', @weekly_every_day.every_day
|
||||
@weekly_every_day.weekly_return_monday=('m')
|
||||
assert_equal 'sm ', @weekly_every_day.every_day
|
||||
@weekly_every_day.weekly_return_tuesday=('t')
|
||||
assert_equal 'smt ', @weekly_every_day.every_day
|
||||
@weekly_every_day.weekly_return_wednesday=('w')
|
||||
assert_equal 'smtw ', @weekly_every_day.every_day
|
||||
@weekly_every_day.weekly_return_thursday=('t')
|
||||
assert_equal 'smtwt ', @weekly_every_day.every_day
|
||||
@weekly_every_day.weekly_return_friday=('f')
|
||||
assert_equal 'smtwtf ', @weekly_every_day.every_day
|
||||
@weekly_every_day.weekly_return_saturday=('s')
|
||||
assert_equal 'smtwtfs', @weekly_every_day.every_day
|
||||
|
||||
# test remove
|
||||
@weekly_every_day.weekly_return_wednesday=(' ')
|
||||
assert_equal 'smt tfs', @weekly_every_day.every_day
|
||||
end
|
||||
|
||||
def test_weekly_pattern
|
||||
assert_equal true, @weekly_every_day.continues_recurring?(nil)
|
||||
|
||||
due_date = @weekly_every_day.get_due_date(@sunday)
|
||||
assert_equal @monday, due_date
|
||||
|
||||
# saturday is last day in week, so the next date should be sunday + n-1 weeks
|
||||
# n-1 because sunday is already in the next week
|
||||
@weekly_every_day.every_other1 = 3
|
||||
due_date = @weekly_every_day.get_due_date(@saturday)
|
||||
assert_equal @sunday + 2.weeks, due_date
|
||||
|
||||
# remove tuesday and wednesday
|
||||
@weekly_every_day.weekly_return_tuesday=(' ')
|
||||
@weekly_every_day.weekly_return_wednesday=(' ')
|
||||
assert_equal 'sm tfs', @weekly_every_day.every_day
|
||||
due_date = @weekly_every_day.get_due_date(@monday)
|
||||
assert_equal @thursday, due_date
|
||||
|
||||
@weekly_every_day.every_other1 = 1
|
||||
@weekly_every_day.every_day = ' tw '
|
||||
due_date = @weekly_every_day.get_due_date(@tuesday)
|
||||
assert_equal @wednesday, due_date
|
||||
due_date = @weekly_every_day.get_due_date(@wednesday)
|
||||
assert_equal @tuesday+1.week, due_date
|
||||
|
||||
@weekly_every_day.every_day = ' s'
|
||||
due_date = @weekly_every_day.get_due_date(@sunday)
|
||||
assert_equal @saturday+1.week, due_date
|
||||
end
|
||||
|
||||
def test_monthly_pattern
|
||||
due_date = @monthly_every_last_friday.get_due_date(@sunday)
|
||||
assert_equal Time.zone.local(2008,6,27), due_date
|
||||
|
||||
friday_is_last_day_of_month = Time.zone.local(2008,10,31)
|
||||
due_date = @monthly_every_last_friday.get_due_date(friday_is_last_day_of_month-1.day )
|
||||
assert_equal friday_is_last_day_of_month , due_date
|
||||
|
||||
@monthly_every_third_friday = @monthly_every_last_friday
|
||||
@monthly_every_third_friday.every_other3=3 #third
|
||||
due_date = @monthly_every_last_friday.get_due_date(@sunday) # june 8th 2008
|
||||
assert_equal Time.zone.local(2008, 6, 20), due_date
|
||||
# set date past third friday of this month
|
||||
due_date = @monthly_every_last_friday.get_due_date(Time.zone.local(2008,6,21)) # june 21th 2008
|
||||
assert_equal Time.zone.local(2008, 8, 15), due_date # every 2 months, so aug
|
||||
|
||||
@monthly = @monthly_every_last_friday
|
||||
@monthly.recurrence_selector=0
|
||||
@monthly.every_other1 = 8 # every 8th day of the month
|
||||
@monthly.every_other2 = 2 # every 2 months
|
||||
|
||||
due_date = @monthly.get_due_date(@saturday) # june 7th
|
||||
assert_equal @sunday, due_date # june 8th
|
||||
|
||||
due_date = @monthly.get_due_date(@sunday) # june 8th
|
||||
assert_equal Time.zone.local(2008,8,8), due_date # aug 8th
|
||||
end
|
||||
|
||||
def test_yearly_pattern
|
||||
# beginning of same year
|
||||
due_date = @yearly.get_due_date(Time.zone.local(2008,2,10)) # feb 10th
|
||||
assert_equal @sunday, due_date # june 8th
|
||||
|
||||
# same month, previous date
|
||||
due_date = @yearly.get_due_date(@saturday) # june 7th
|
||||
show_from_date = @yearly.get_show_from_date(@saturday) # june 7th
|
||||
assert_equal @sunday, due_date # june 8th
|
||||
assert_equal @sunday-5.days, show_from_date
|
||||
|
||||
# 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
|
||||
@yearly.every_count = 3 # wednesday
|
||||
# beginning of same year
|
||||
due_date = @yearly.get_due_date(Time.zone.local(2008,2,10)) # feb 10th
|
||||
assert_equal Time.zone.local(2008,6,11), due_date # june 11th
|
||||
# same month, before second wednesday
|
||||
due_date = @yearly.get_due_date(@saturday) # june 7th
|
||||
assert_equal Time.zone.local(2008,6,11), due_date # june 11th
|
||||
# same month, after second wednesday
|
||||
due_date = @yearly.get_due_date(Time.zone.local(2008,6,12)) # june 7th
|
||||
assert_equal Time.zone.local(2009,6,10), due_date # june 10th
|
||||
end
|
||||
|
||||
def test_next_todo_without_previous_todo
|
||||
# test handling of nil as previous
|
||||
#
|
||||
# start_from is way_back
|
||||
due_date1 = @yearly.get_due_date(nil)
|
||||
due_date2 = @yearly.get_due_date(Time.now.utc + 1.day)
|
||||
assert_equal due_date1, due_date2
|
||||
|
||||
# start_from is in the future
|
||||
@yearly.start_from = Time.now.utc + 1.week
|
||||
due_date1 = @yearly.get_due_date(nil)
|
||||
due_date2 = @yearly.get_due_date(Time.now.utc + 1.day)
|
||||
assert_equal due_date1, due_date2
|
||||
|
||||
# start_from is nil
|
||||
@yearly.start_from = nil
|
||||
due_date1 = @yearly.get_due_date(nil)
|
||||
due_date2 = @yearly.get_due_date(Time.now.utc + 1.day)
|
||||
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
|
||||
due_date = @every_day.get_due_date(nil)
|
||||
assert_equal @in_three_days, due_date
|
||||
due_date = @every_day.get_due_date(@tomorrow)
|
||||
assert_equal @in_three_days, due_date
|
||||
|
||||
# if we give a date in the future for the previous todo, the next to do
|
||||
# should be based on that future date.
|
||||
due_date = @every_day.get_due_date(@in_four_days)
|
||||
assert_equal @in_four_days+1.day, due_date
|
||||
|
||||
@weekly_every_day.start_from = Time.zone.local(2020,1,1)
|
||||
assert_equal Time.zone.local(2020,1,1), @weekly_every_day.get_due_date(nil)
|
||||
assert_equal Time.zone.local(2020,1,1), @weekly_every_day.get_due_date(Time.zone.local(2019,10,1))
|
||||
assert_equal Time.zone.local(2020,1,10), @weekly_every_day.get_due_date(Time.zone.local(2020,1,9))
|
||||
|
||||
@monthly_every_last_friday.start_from = Time.zone.local(2020,1,1)
|
||||
assert_equal Time.zone.local(2020,1,31), @monthly_every_last_friday.get_due_date(nil) # last friday of jan
|
||||
assert_equal Time.zone.local(2020,1,31), @monthly_every_last_friday.get_due_date(Time.zone.local(2019,12,1)) # last friday of jan
|
||||
assert_equal Time.zone.local(2020,2,28), @monthly_every_last_friday.get_due_date(Time.zone.local(2020,2,1)) # last friday of feb
|
||||
|
||||
# start from after june 8th 2008
|
||||
@yearly.start_from = Time.zone.local(2020,6,12)
|
||||
assert_equal Time.zone.local(2021,6,8), @yearly.get_due_date(nil) # jun 8th next year
|
||||
assert_equal Time.zone.local(2021,6,8), @yearly.get_due_date(Time.zone.local(2019,6,1)) # also next year
|
||||
assert_equal Time.zone.local(2021,6,8), @yearly.get_due_date(Time.zone.local(2020,6,15)) # also next year
|
||||
|
||||
this_year = Time.now.utc.year
|
||||
@yearly.start_from = Time.zone.local(this_year+1,6,12)
|
||||
due_date = @yearly.get_due_date(nil)
|
||||
assert_equal due_date.year, this_year+2
|
||||
end
|
||||
|
||||
def test_toggle_completion
|
||||
assert @yearly.active?
|
||||
assert @yearly.toggle_completion!
|
||||
assert @yearly.completed?
|
||||
|
||||
# entering completed state should set completed_at
|
||||
assert !@yearly.completed_at.nil?
|
||||
|
||||
assert @yearly.toggle_completion!
|
||||
assert @yearly.active?
|
||||
|
||||
# re-entering active state should clear completed_at
|
||||
assert @yearly.completed_at.nil?
|
||||
end
|
||||
|
||||
def test_starred
|
||||
@yearly.tag_with("1, 2, starred")
|
||||
@yearly.tags.reload
|
||||
|
||||
assert @yearly.starred?
|
||||
assert !@weekly_every_day.starred?
|
||||
|
||||
@yearly.toggle_star!
|
||||
assert !@yearly.starred?
|
||||
@yearly.toggle_star!
|
||||
assert @yearly.starred?
|
||||
end
|
||||
|
||||
def test_occurence_count
|
||||
@every_day.number_of_occurences = 2
|
||||
assert_equal true, @every_day.continues_recurring?(@in_three_days)
|
||||
@every_day.increment_occurrences
|
||||
assert_equal true, @every_day.continues_recurring?(@in_three_days)
|
||||
@every_day.increment_occurrences
|
||||
assert_equal false, @every_day.continues_recurring?(@in_three_days)
|
||||
|
||||
# after completion, when you reactivate the recurring todo, the occurences
|
||||
# count should be reset
|
||||
assert_equal 2, @every_day.occurences_count
|
||||
assert @every_day.toggle_completion!
|
||||
assert @every_day.toggle_completion!
|
||||
|
||||
assert_equal true, @every_day.continues_recurring?(@in_three_days)
|
||||
assert_equal 0, @every_day.occurences_count
|
||||
end
|
||||
|
||||
def test_invalid_recurring_period_will_not_save
|
||||
@every_day.recurring_period = 'invalid'
|
||||
assert !@every_day.valid?
|
||||
|
||||
@every_month.recurrence_selector = 99
|
||||
assert_raise(Exception){ @every_month.valid? }
|
||||
|
||||
@yearly.recurrence_selector = 99
|
||||
assert_raise(Exception){ @yearly.valid? }
|
||||
end
|
||||
|
||||
def test_every_n_the_day_must_be_filled
|
||||
@every_day.every_other1 = nil
|
||||
assert !@every_day.valid?
|
||||
end
|
||||
|
||||
def test_every_n_week_must_be_filled
|
||||
@every_week.every_other1 = nil
|
||||
assert !@every_week.valid?
|
||||
end
|
||||
|
||||
def test_every_n_month_must_be_filled
|
||||
@every_month.every_other1 = nil
|
||||
@every_month.every_other2 = nil
|
||||
assert !@every_month.valid?
|
||||
|
||||
@every_month.recurrence_selector = 0
|
||||
assert !@every_month.valid?
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
57
test/models/staleness_test.rb
Normal file
57
test/models/staleness_test.rb
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
require_relative '../minimal_test_helper'
|
||||
require_relative '../../lib/staleness'
|
||||
|
||||
|
||||
class StalenessTest < Test::Unit::TestCase
|
||||
FakeUser = Struct.new(:time)
|
||||
FakeTask = Struct.new(:due, :completed, :created_at) do
|
||||
def completed?
|
||||
self.completed
|
||||
end
|
||||
end
|
||||
|
||||
def now
|
||||
@now ||= Time.utc(2013, 2, 28, 0, 0, 0)
|
||||
end
|
||||
|
||||
def after_now
|
||||
@after_now ||= Time.utc(2013, 3, 1, 0, 0, 0)
|
||||
end
|
||||
|
||||
def day16
|
||||
@day16 ||= Time.utc(2013, 2, 12, 0, 0, 0)
|
||||
end
|
||||
|
||||
def day8
|
||||
@day8 ||= Time.utc(2013, 2, 20, 0, 0, 0)
|
||||
end
|
||||
|
||||
def setup
|
||||
@current_user = FakeUser.new(now)
|
||||
end
|
||||
|
||||
def test_item_with_due_date_is_not_stale_ever
|
||||
todo = FakeTask.new(now, false, day8)
|
||||
assert_equal 0, Staleness.days_stale(todo, @current_user)
|
||||
end
|
||||
|
||||
def test_complete_item_is_not_stale
|
||||
todo = FakeTask.new(day8, true, day16)
|
||||
assert_equal 0, Staleness.days_stale(todo, @current_user)
|
||||
end
|
||||
|
||||
def test_created_at_after_current_time_is_not_stale
|
||||
todo = FakeTask.new(nil, false, after_now)
|
||||
assert_equal 0, Staleness.days_stale(todo, @current_user)
|
||||
end
|
||||
|
||||
def test_young_item_is_not_stale
|
||||
todo = FakeTask.new(nil, false, now)
|
||||
assert_equal 0, Staleness.days_stale(todo, @current_user)
|
||||
end
|
||||
|
||||
def test_todo_staleness_calculation
|
||||
todo = FakeTask.new(nil, false, day8)
|
||||
assert_equal 8, Staleness.days_stale(todo, @current_user)
|
||||
end
|
||||
end
|
||||
31
test/models/tag_cloud_query_test.rb
Normal file
31
test/models/tag_cloud_query_test.rb
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class TagCloudQueryTest < ActiveSupport::TestCase
|
||||
|
||||
fixtures :tags, :taggings, :users
|
||||
|
||||
def user
|
||||
@user ||= User.find 1
|
||||
end
|
||||
|
||||
def test_get_all_tags
|
||||
tags = Stats::TagCloudQuery.new(user).result
|
||||
assert_equal 2, tags.size
|
||||
tags.sort_by! {|t| t.id}
|
||||
tag = tags.first
|
||||
assert_equal 3, tag.count
|
||||
assert_equal "foo", tag.name
|
||||
|
||||
tag = tags.last
|
||||
assert_equal 1, tag.count
|
||||
assert_equal "bar", tag.name
|
||||
end
|
||||
|
||||
def test_get_subset_of_tags
|
||||
tags = Stats::TagCloudQuery.new(user, 1.week.ago).result
|
||||
|
||||
assert_equal 1, tags.size
|
||||
assert_equal 2, tags.first.count
|
||||
assert_equal "foo", tags.first.name
|
||||
end
|
||||
end
|
||||
31
test/models/tag_cloud_test.rb
Normal file
31
test/models/tag_cloud_test.rb
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../minimal_test_helper')
|
||||
require 'app/models/stats/tag_cloud'
|
||||
|
||||
class TagCloudTest < Test::Unit::TestCase
|
||||
|
||||
FakeTag = Struct.new(:name, :count)
|
||||
|
||||
def test_tags_get_sorted_alphabetically
|
||||
tags = [FakeTag.new("bee", 1), FakeTag.new("See", 10), FakeTag.new("aye", 100)]
|
||||
|
||||
assert_equal %w(aye bee See), Stats::TagCloud.new(tags).tags.map(&:name)
|
||||
end
|
||||
|
||||
def test_tag_relative_size
|
||||
tags = [FakeTag.new("bee", 1), FakeTag.new("See", 10), FakeTag.new("aye", 100)]
|
||||
cloud = Stats::TagCloud.new(tags)
|
||||
|
||||
assert_equal 0, cloud.relative_size(FakeTag.new("whatever", 1))
|
||||
assert_equal 4, cloud.relative_size(FakeTag.new("whatever", 50))
|
||||
assert_equal 9, cloud.relative_size(FakeTag.new("whatever", 100))
|
||||
end
|
||||
|
||||
def test_empty_tags
|
||||
cloud = Stats::TagCloud.new([])
|
||||
assert cloud.empty?
|
||||
|
||||
cloud = Stats::TagCloud.new([FakeTag.new("Tag", 1)])
|
||||
assert !cloud.empty?
|
||||
end
|
||||
|
||||
end
|
||||
54
test/models/tag_test.rb
Normal file
54
test/models/tag_test.rb
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class TagTest < ActiveSupport::TestCase
|
||||
fixtures :tags
|
||||
|
||||
def test_find_or_create_with_single_word
|
||||
tag = Tag.where(:name => "test").first_or_create
|
||||
assert !tag.new_record?
|
||||
end
|
||||
|
||||
def test_find_or_create_with_space
|
||||
tag = Tag.where(:name => "test test").first_or_create
|
||||
assert !tag.new_record?
|
||||
end
|
||||
|
||||
def test_find_or_create_with_dot
|
||||
tag = Tag.where(:name => "a.b.c").first_or_create
|
||||
assert !tag.new_record?
|
||||
end
|
||||
|
||||
def test_find_or_create_with_number_as_string
|
||||
tag = Tag.where(:name => "12343").first_or_create
|
||||
assert !tag.new_record?
|
||||
|
||||
tag = Tag.where(:name => "8.1.2").first_or_create
|
||||
assert !tag.new_record?
|
||||
end
|
||||
|
||||
def test_tag_name_always_lowercase
|
||||
tag = Tag.where(:name => "UPPER").first_or_create
|
||||
assert !tag.new_record?
|
||||
|
||||
upper = Tag.where(:name => "upper").first
|
||||
assert_not_nil upper
|
||||
assert upper.name == "upper"
|
||||
end
|
||||
|
||||
def test_tag_name_stripped_of_spaces
|
||||
tag = Tag.where(:name => " strip spaces ").first_or_create
|
||||
assert !tag.new_record?
|
||||
|
||||
assert tag.name == "strip spaces"
|
||||
end
|
||||
|
||||
def test_tag_label
|
||||
assert_equal 'one-two-three', Tag.new(:name => 'one two three').label
|
||||
end
|
||||
|
||||
def test_tag_as_string
|
||||
tags = [Tag.new(:name => 'tag1'), Tag.new(:name => 'tag2')]
|
||||
assert_equal 'tag1, tag2', tags.join(', ')
|
||||
end
|
||||
|
||||
end
|
||||
16
test/models/tagging_test.rb
Normal file
16
test/models/tagging_test.rb
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class TaggingTest < ActiveSupport::TestCase
|
||||
fixtures :taggings, :tags
|
||||
|
||||
def test_removes_unused_tags
|
||||
tag = Tag.create!(:name => "hello")
|
||||
tagging = Tagging.create!(:tag => tag, :taggable_id => 1)
|
||||
|
||||
assert_equal 1, Tagging.find(:all, :conditions => ["tag_id = ?", tag.id]).count
|
||||
|
||||
tagging.destroy
|
||||
|
||||
assert_nil Tag.where(:name => "hello").first
|
||||
end
|
||||
end
|
||||
93
test/models/time_to_complete_test.rb
Normal file
93
test/models/time_to_complete_test.rb
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
require 'date'
|
||||
require 'time'
|
||||
require './test/minimal_test_helper'
|
||||
require 'app/models/stats/time_to_complete'
|
||||
|
||||
FakeTask = Struct.new(:created_at, :completed_at)
|
||||
|
||||
class TimeToCompleteTest < Test::Unit::TestCase
|
||||
|
||||
def now
|
||||
@now ||= Time.utc(2013, 1, 2, 3, 4, 5)
|
||||
end
|
||||
|
||||
def day0
|
||||
@day0 ||= Time.utc(2013, 1, 2, 0, 0, 0)
|
||||
end
|
||||
|
||||
def day2
|
||||
@day2 ||= Time.utc(2012, 12, 31, 0, 0, 0)
|
||||
end
|
||||
|
||||
def day4
|
||||
@day4 ||= Time.utc(2012, 12, 29, 0, 0, 0)
|
||||
end
|
||||
|
||||
def day6
|
||||
@day6 ||= Time.utc(2012, 12, 27, 0, 0, 0)
|
||||
end
|
||||
|
||||
def fake_tasks
|
||||
@fake_tasks ||= [
|
||||
FakeTask.new(day2, now),
|
||||
FakeTask.new(day4, now),
|
||||
FakeTask.new(day6, now)
|
||||
]
|
||||
end
|
||||
|
||||
def test_empty_minimum
|
||||
assert_equal 0, Stats::TimeToComplete.new([]).min
|
||||
end
|
||||
|
||||
def test_empty_maximum
|
||||
assert_equal 0, Stats::TimeToComplete.new([]).max
|
||||
end
|
||||
|
||||
def test_empty_avg
|
||||
assert_equal 0, Stats::TimeToComplete.new([]).avg
|
||||
end
|
||||
|
||||
def test_empty_min_sec
|
||||
assert_equal '00:00:00', Stats::TimeToComplete.new([]).min_sec
|
||||
end
|
||||
|
||||
def test_minimum
|
||||
assert_equal 2.1, Stats::TimeToComplete.new(fake_tasks).min
|
||||
end
|
||||
|
||||
def test_maximum
|
||||
assert_equal 6.1, Stats::TimeToComplete.new(fake_tasks).max
|
||||
end
|
||||
|
||||
def test_avg
|
||||
assert_equal 4.1, Stats::TimeToComplete.new(fake_tasks).avg
|
||||
end
|
||||
|
||||
def test_min_sec
|
||||
assert_equal '2 days 03:04:05', Stats::TimeToComplete.new(fake_tasks).min_sec
|
||||
end
|
||||
|
||||
def test_min_sec_with_less_than_a_day
|
||||
task = FakeTask.new(day0, now)
|
||||
assert_equal '03:04:05', Stats::TimeToComplete.new([task]).min_sec
|
||||
end
|
||||
|
||||
def test_rounding
|
||||
start_time = Time.utc(2012, 12, 31, 8, 0, 0)
|
||||
task = FakeTask.new(start_time, now)
|
||||
ttc = Stats::TimeToComplete.new([task])
|
||||
assert_equal 1.8, ttc.avg
|
||||
assert_equal 1.8, ttc.min
|
||||
assert_equal 1.8, ttc.max
|
||||
end
|
||||
|
||||
def test_min_sec_with_almost_three_days
|
||||
start_time = Time.utc(2012, 12, 30, 8, 0, 0)
|
||||
task = FakeTask.new(start_time, now)
|
||||
stats = Stats::TimeToComplete.new([task])
|
||||
assert_equal 2.8, stats.min
|
||||
assert_equal '2 days 19:04:05', stats.min_sec
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
123
test/models/todo_create_params_helper_test.rb
Normal file
123
test/models/todo_create_params_helper_test.rb
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
require 'todos_controller'
|
||||
|
||||
class TodoCreateParamsHelperTest < ActiveSupport::TestCase
|
||||
|
||||
def test_works_with_request_as_root_hash_entry
|
||||
params = {'request' => { 'todo' => { 'description' => 'foo'}}}
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal({'description' => 'foo'}, params_helper.attributes)
|
||||
end
|
||||
|
||||
def test_works_with_todo_as_root_hash_entry
|
||||
params = { 'todo' => { 'description' => 'foo'}}
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal({'description' => 'foo'}, params_helper.attributes)
|
||||
end
|
||||
|
||||
def test_show_from_accessor
|
||||
expected_date = Time.now
|
||||
params = { 'todo' => { 'show_from' => expected_date}}
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal(expected_date, params_helper.show_from)
|
||||
end
|
||||
|
||||
def test_due_accessor
|
||||
expected_date = Time.now
|
||||
params = { 'todo' => { 'due' => expected_date}}
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal(expected_date, params_helper.due)
|
||||
end
|
||||
|
||||
def test_tag_list_accessor
|
||||
params = { 'todo' => { }, 'tag_list' => 'foo, bar'}
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal('foo, bar', params_helper.tag_list)
|
||||
end
|
||||
|
||||
def test_parse_dates_parses_show_from_date_based_on_prefs
|
||||
params = { 'todo' => { 'show_from' => '20/05/07', 'due' => '23/5/07'}}
|
||||
|
||||
user = users(:admin_user)
|
||||
prefs = user.prefs
|
||||
prefs.date_format = "%d/%m/%y" # make sure the format matches the above
|
||||
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, user)
|
||||
params_helper.parse_dates()
|
||||
assert_equal Date.new(2007, 5, 20), params_helper.show_from.to_date
|
||||
end
|
||||
|
||||
def test_parse_dates_parses_due_date_based_on_prefs
|
||||
params = { 'todo' => { 'show_from' => '20/5/07', 'due' => '23/5/07'}}
|
||||
|
||||
user = users(:admin_user)
|
||||
prefs = user.prefs
|
||||
prefs.date_format = "%d/%m/%y" # make sure the format matches the above
|
||||
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, user)
|
||||
params_helper.parse_dates()
|
||||
assert_equal Date.new(2007, 5, 23), params_helper.due.to_date
|
||||
end
|
||||
|
||||
def test_parse_dates_sets_due_to_empty_string_if_nil
|
||||
params = { 'todo' => { 'show_from' => '20/5/07', 'due' => nil}}
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
params_helper.parse_dates()
|
||||
assert_equal '', params_helper.due
|
||||
end
|
||||
|
||||
def test_project_name_is_stripped_of_leading_and_trailing_whitespace
|
||||
params = { 'project_name' => ' Visit New Orleans ' }
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal 'Visit New Orleans', params_helper.project_name
|
||||
end
|
||||
|
||||
def test_project_name_is_nil_when_unspecified
|
||||
params = { }
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_nil params_helper.project_name
|
||||
end
|
||||
|
||||
def test_context_name_is_stripped_of_leading_and_trailing_whitespace
|
||||
params = { 'context_name' => ' mobile phone ' }
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal 'mobile phone', params_helper.context_name
|
||||
end
|
||||
|
||||
def test_context_name_is_nil_when_unspecified
|
||||
params = { }
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_nil params_helper.context_name
|
||||
end
|
||||
|
||||
def test_project_specified_by_name_is_false_when_project_id_is_specified
|
||||
params = { 'todo' => { 'project_id' => 2 } }
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal false, params_helper.project_specified_by_name?
|
||||
end
|
||||
|
||||
def test_project_specified_by_name_is_false_when_project_name_is_blank
|
||||
params = { 'project_name' => nil, 'todo' => {} }
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal false, params_helper.project_specified_by_name?
|
||||
end
|
||||
|
||||
def test_project_specified_by_name_is_false_when_project_name_is_none
|
||||
params = { 'project_name' => 'None', 'todo' => {} }
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal false, params_helper.project_specified_by_name?
|
||||
end
|
||||
|
||||
def test_context_specified_by_name_is_false_when_context_id_is_specified
|
||||
params = { 'todo' => { 'context_id' => 3 } }
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal false, params_helper.context_specified_by_name?
|
||||
end
|
||||
|
||||
def test_context_specified_by_name_is_false_when_context_name_is_blank
|
||||
params = { 'context_name' => nil, 'todo' => {} }
|
||||
params_helper = Todos::TodoCreateParamsHelper.new(params, users(:admin_user))
|
||||
assert_equal false, params_helper.context_specified_by_name?
|
||||
end
|
||||
|
||||
end
|
||||
471
test/models/todo_test.rb
Normal file
471
test/models/todo_test.rb
Normal file
|
|
@ -0,0 +1,471 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class TodoTest < ActiveSupport::TestCase
|
||||
fixtures :todos, :recurring_todos, :users, :contexts, :preferences, :tags, :taggings, :projects
|
||||
|
||||
def setup
|
||||
@not_completed1 = Todo.find(1).reload
|
||||
@not_completed2 = Todo.find(2).reload
|
||||
@completed = Todo.find(8).reload
|
||||
end
|
||||
|
||||
# Test loading a todo item
|
||||
def test_load
|
||||
assert_kind_of Todo, @not_completed1
|
||||
assert_equal 1, @not_completed1.id
|
||||
assert_equal 1, @not_completed1.context_id
|
||||
assert_equal 2, @not_completed1.project_id
|
||||
assert_equal "Call Bill Gates to find out how much he makes per day", @not_completed1.description
|
||||
assert_nil @not_completed1.notes
|
||||
assert @not_completed1.completed? == false
|
||||
assert_equal 1.week.ago.beginning_of_day.strftime("%Y-%m-%d %H:%M"), @not_completed1.created_at.strftime("%Y-%m-%d %H:%M")
|
||||
assert_equal 2.week.from_now.beginning_of_day.strftime("%Y-%m-%d"), @not_completed1.due.strftime("%Y-%m-%d")
|
||||
assert_nil @not_completed1.completed_at
|
||||
assert_equal 1, @not_completed1.user_id
|
||||
end
|
||||
|
||||
def test_completed
|
||||
assert_kind_of Todo, @completed
|
||||
assert @completed.completed?
|
||||
assert_not_nil @completed.completed_at
|
||||
end
|
||||
|
||||
def test_completed_at_cleared_after_toggle_to_active
|
||||
assert_kind_of Todo, @completed
|
||||
assert @completed.completed?
|
||||
@completed.toggle_completion!
|
||||
assert @completed.active?
|
||||
assert_nil @completed.completed_at
|
||||
end
|
||||
|
||||
|
||||
# Validation tests
|
||||
#
|
||||
def test_validate_presence_of_description
|
||||
assert_equal "Call dinosaur exterminator", @not_completed2.description
|
||||
@not_completed2.description = ""
|
||||
assert !@not_completed2.save
|
||||
assert_equal 1, @not_completed2.errors.count
|
||||
assert_equal "can't be blank", @not_completed2.errors[:description][0]
|
||||
end
|
||||
|
||||
def test_validate_length_of_description
|
||||
assert_equal "Call dinosaur exterminator", @not_completed2.description
|
||||
@not_completed2.description = generate_random_string(101)
|
||||
assert !@not_completed2.save
|
||||
assert_equal 1, @not_completed2.errors.count
|
||||
assert_equal "is too long (maximum is 100 characters)", @not_completed2.errors[:description][0]
|
||||
end
|
||||
|
||||
def test_validate_length_of_notes
|
||||
assert_equal "Ask him if I need to hire a skip for the corpses.", @not_completed2.notes
|
||||
@not_completed2.notes = generate_random_string(60001)
|
||||
assert !@not_completed2.save
|
||||
assert_equal 1, @not_completed2.errors.count
|
||||
assert_equal "is too long (maximum is 60000 characters)", @not_completed2.errors[:notes][0]
|
||||
end
|
||||
|
||||
def test_validate_show_from_must_be_a_date_in_the_future
|
||||
t = @not_completed2
|
||||
t.show_from = 1.week.ago
|
||||
|
||||
assert !t.save, "todo should not be saved without validation errors"
|
||||
assert_equal 1, t.errors.count
|
||||
assert_equal "must be a date in the future", t.errors[:show_from][0]
|
||||
end
|
||||
|
||||
def test_validate_circular_dependencies
|
||||
@completed.activate!
|
||||
@not_completed3=@completed
|
||||
|
||||
# 2 -> 1
|
||||
@not_completed1.add_predecessor(@not_completed2)
|
||||
assert @not_completed1.save!
|
||||
assert_equal 1, @not_completed2.successors.count
|
||||
|
||||
# 3 -> 2 -> 1
|
||||
@not_completed2.add_predecessor(@not_completed3)
|
||||
assert @not_completed2.save!
|
||||
assert_equal 1, @not_completed3.successors.count
|
||||
|
||||
# 1 -> 3 -> 2 -> 1 == circle
|
||||
@not_completed3.add_predecessor(@not_completed1)
|
||||
assert !@not_completed3.valid?
|
||||
error_msg = "Adding ''Call Bill Gates to find out how much he makes per day' <'agenda'; 'Make more money than Billy Gates'>' would create a circular dependency"
|
||||
assert_equal error_msg, @not_completed3.errors["Depends on:"][0]
|
||||
end
|
||||
|
||||
def test_defer_an_existing_todo
|
||||
@not_completed2
|
||||
assert_equal :active, @not_completed2.aasm_current_state
|
||||
@not_completed2.show_from = Time.zone.now + 1.week
|
||||
assert @not_completed2.save, "should have saved successfully" + @not_completed2.errors.to_xml
|
||||
assert_equal :deferred, @not_completed2.aasm_current_state
|
||||
end
|
||||
|
||||
def test_create_a_new_deferred_todo
|
||||
user = users(:other_user)
|
||||
todo = user.todos.build
|
||||
todo.show_from = next_week
|
||||
todo.context_id = 1
|
||||
todo.description = 'foo'
|
||||
assert todo.save, "should have saved successfully" + todo.errors.to_xml
|
||||
assert_equal :deferred, todo.aasm_current_state
|
||||
end
|
||||
|
||||
def test_create_a_new_deferred_todo_by_passing_attributes
|
||||
user = users(:other_user)
|
||||
todo = user.todos.build(:show_from => next_week, :context_id => 1, :description => 'foo')
|
||||
assert todo.save, "should have saved successfully" + todo.errors.to_xml
|
||||
assert_equal :deferred, todo.aasm_current_state
|
||||
end
|
||||
|
||||
def test_toggle_completion
|
||||
t = @not_completed1
|
||||
assert_equal :active, t.aasm_current_state
|
||||
t.toggle_completion!
|
||||
assert_equal :completed, t.aasm_current_state
|
||||
t.toggle_completion!
|
||||
assert_equal :active, t.aasm_current_state
|
||||
end
|
||||
|
||||
def test_toggle_completion_with_show_from_in_future
|
||||
t = @not_completed1
|
||||
t.show_from= 1.week.from_now
|
||||
t.save!
|
||||
assert_equal :deferred, t.aasm_current_state
|
||||
t.toggle_completion!
|
||||
assert_equal :completed, t.aasm_current_state
|
||||
end
|
||||
|
||||
def test_toggle_completion_with_show_from_in_past
|
||||
t = @not_completed1
|
||||
t.update_attribute(:show_from, 1.week.ago)
|
||||
assert_equal :active, t.aasm_current_state
|
||||
|
||||
assert t.toggle_completion!, "shoud be able to mark active todo complete even if show_from is set in the past"
|
||||
assert_equal :completed, t.aasm_current_state
|
||||
end
|
||||
|
||||
def test_activate_also_saves
|
||||
t = @not_completed1
|
||||
t.show_from = 1.week.from_now
|
||||
t.save!
|
||||
assert t.deferred?
|
||||
t.reload
|
||||
t.activate!
|
||||
assert t.active?
|
||||
t.reload
|
||||
assert t.active?
|
||||
end
|
||||
|
||||
def test_activate_also_clears_show_from
|
||||
# setup test case
|
||||
t = @not_completed1
|
||||
t.show_from = 1.week.from_now
|
||||
t.save!
|
||||
assert t.deferred?
|
||||
t.reload
|
||||
|
||||
# activate and check show_from
|
||||
t.activate!
|
||||
assert t.active?
|
||||
assert t.show_from.nil?
|
||||
end
|
||||
|
||||
def test_clearing_show_from_activates_todo
|
||||
t = @not_completed1
|
||||
t.show_from = 1.week.from_now
|
||||
t.save!
|
||||
t.reload
|
||||
|
||||
assert t.deferred?
|
||||
|
||||
t.show_from = nil
|
||||
t.save!
|
||||
t.reload
|
||||
|
||||
assert t.active?
|
||||
end
|
||||
|
||||
def test_project_returns_null_object_when_nil
|
||||
t = @not_completed1
|
||||
assert !t.project.is_a?(NullProject)
|
||||
t.project = nil
|
||||
assert t.project.is_a?(NullProject)
|
||||
end
|
||||
|
||||
def test_initial_state_defaults_to_active
|
||||
t = Todo.new
|
||||
t.description = 'foo'
|
||||
t.context_id = 1
|
||||
t.save!
|
||||
t.reload
|
||||
assert_equal :active, t.aasm_current_state
|
||||
end
|
||||
|
||||
def test_initial_state_is_deferred_when_show_from_in_future
|
||||
t = Todo.new
|
||||
t.user = users(:admin_user)
|
||||
t.description = 'foo'
|
||||
t.context_id = 1
|
||||
t.show_from = 1.week.from_now.to_date
|
||||
t.save!
|
||||
t.reload
|
||||
assert_equal :deferred, t.aasm_current_state
|
||||
end
|
||||
|
||||
def test_todo_is_not_starred
|
||||
assert !@not_completed1.starred?
|
||||
end
|
||||
|
||||
def test_todo_2_is_not_starred
|
||||
assert !Todo.find(2).starred?
|
||||
end
|
||||
|
||||
def test_todo_is_starred_after_starred_tag_is_added
|
||||
@not_completed1._add_tags('starred')
|
||||
assert @not_completed1.starred?
|
||||
end
|
||||
|
||||
def test_todo_is_starred_after_toggle_starred
|
||||
@not_completed1.toggle_star!
|
||||
assert @not_completed1.starred?
|
||||
end
|
||||
|
||||
def test_todo_is_not_starred_after_toggle_starred_twice
|
||||
@not_completed1.toggle_star!
|
||||
@not_completed1.toggle_star!
|
||||
assert !@not_completed1.starred?
|
||||
end
|
||||
|
||||
def test_todo_specification_handles_null_project
|
||||
# @not_completed1 has a project
|
||||
todo_desc = @not_completed1.description
|
||||
assert_equal "'#{todo_desc}' <'agenda'; 'Make more money than Billy Gates'>", @not_completed1.specification
|
||||
|
||||
# now check on null
|
||||
@not_completed1.project = nil
|
||||
@not_completed1.save
|
||||
assert_equal "'#{todo_desc}' <'agenda'; '(none)'>", @not_completed1.specification
|
||||
end
|
||||
|
||||
def test_add_predecessor_list
|
||||
todo = Todo.new
|
||||
|
||||
single = @not_completed1.id.to_s
|
||||
multi = single + ", " + @not_completed2.id.to_s # note one space after comma
|
||||
|
||||
@predecessor_array = todo.add_predecessor_list(single)
|
||||
assert_not_nil @predecessor_array
|
||||
assert_equal 1, @predecessor_array.size
|
||||
|
||||
@predecessor_array = todo.add_predecessor_list(multi)
|
||||
assert_not_nil @predecessor_array
|
||||
assert_equal 2, @predecessor_array.size
|
||||
end
|
||||
|
||||
def test_add_predecessor_list_with_comma
|
||||
# test for #975
|
||||
todo = Todo.new
|
||||
|
||||
@not_completed1.description = "test,1,2,3"
|
||||
@not_completed1.save
|
||||
@not_completed2.description = "test,4,5,6"
|
||||
@not_completed2.save
|
||||
|
||||
single = @not_completed1.id.to_s
|
||||
multi = single + "," + @not_completed2.id.to_s # note no space after comma
|
||||
|
||||
@predecessor_array = todo.add_predecessor_list(single)
|
||||
assert_not_nil @predecessor_array
|
||||
assert_equal 1, @predecessor_array.size
|
||||
|
||||
@predecessor_array = todo.add_predecessor_list(multi)
|
||||
assert_not_nil @predecessor_array
|
||||
assert_equal 2, @predecessor_array.size
|
||||
end
|
||||
|
||||
def test_add_and_remove_precesessor
|
||||
@not_completed1.add_predecessor(@not_completed2)
|
||||
@not_completed1.save_predecessors
|
||||
# blocking is not done automagically
|
||||
@not_completed1.block!
|
||||
|
||||
assert @not_completed1.uncompleted_predecessors?
|
||||
assert @not_completed1.pending?, "a todo with predecessors should be pending"
|
||||
|
||||
@not_completed1.remove_predecessor(@not_completed2)
|
||||
@not_completed1.save_predecessors
|
||||
|
||||
assert !@not_completed1.uncompleted_predecessors?
|
||||
assert @not_completed1.active?, "removing last predecessor should activate todo"
|
||||
end
|
||||
|
||||
def test_finding_todos_with_a_tag
|
||||
todo = @not_completed1
|
||||
todo.tag_list = "a, b, c"
|
||||
todo.save!
|
||||
|
||||
tag_a = Tag.where(:name => "a").first
|
||||
tag_b = Tag.where(:name => "b").first
|
||||
tag_c = Tag.where(:name => "c").first
|
||||
|
||||
todos_with_a = Todo.with_tag(tag_a)
|
||||
assert_equal 1, todos_with_a.count
|
||||
assert_equal todo.description, todos_with_a.first.description
|
||||
|
||||
todos_with_b = Todo.with_tag(tag_b)
|
||||
assert_equal 1, todos_with_b.count
|
||||
assert_equal todo.id, todos_with_b.first.id
|
||||
|
||||
todo2 = @not_completed2
|
||||
todo2.tag_list = "a, c, d"
|
||||
todo2.save!
|
||||
|
||||
tag_d = Tag.where(:name => "d").first
|
||||
|
||||
todos_with_a = Todo.with_tag(tag_a)
|
||||
assert_equal 2, todos_with_a.count
|
||||
|
||||
todos_with_d = Todo.with_tag(tag_d)
|
||||
assert_equal 1, todos_with_d.count
|
||||
end
|
||||
|
||||
def test_finding_todos_with_more_tags_using_OR
|
||||
todo1 = @not_completed1
|
||||
todo1.tag_list = "a, b, c"
|
||||
todo1.save!
|
||||
|
||||
todo2 = @not_completed2
|
||||
todo2.tag_list = "a, c, d"
|
||||
todo2.save!
|
||||
|
||||
tag_a = Tag.where(:name => "a").first
|
||||
tag_b = Tag.where(:name => "b").first
|
||||
tag_c = Tag.where(:name => "c").first
|
||||
tag_d = Tag.where(:name => "d").first
|
||||
|
||||
# overlapping tags
|
||||
tag_ids = [tag_a.id, tag_c.id]
|
||||
todos_with_a_or_c = Todo.with_tags(tag_ids)
|
||||
assert_equal 2, todos_with_a_or_c.count
|
||||
|
||||
# non-overlapping tags
|
||||
tag_ids = [tag_b.id, tag_d.id]
|
||||
todos_with_b_or_d = Todo.with_tags(tag_ids)
|
||||
assert_equal 2, todos_with_b_or_d.count
|
||||
end
|
||||
|
||||
def test_finding_todos_with_more_tags_using_AND
|
||||
todo1 = @not_completed1
|
||||
todo1.tag_list = "a, b, c"
|
||||
todo1.save!
|
||||
|
||||
todo2 = @not_completed2
|
||||
todo2.tag_list = "a, c, d"
|
||||
todo2.save!
|
||||
|
||||
tag_a_id = Tag.where(:name => "a").first.id
|
||||
tag_b_id = Tag.where(:name => "b").first.id
|
||||
|
||||
todos_with_a_and_b = Todo.with_tags([tag_a_id]).with_tags([tag_b_id])
|
||||
assert_equal 1, todos_with_a_and_b.count
|
||||
assert_equal todo1.id, todos_with_a_and_b.first.id
|
||||
end
|
||||
|
||||
def test_finding_todos_with_more_tags_using_AND_and_OR
|
||||
todo1 = @not_completed1
|
||||
todo1.tag_list = "a, b, c"
|
||||
todo1.save!
|
||||
|
||||
todo2 = @not_completed2
|
||||
todo2.tag_list = "a, c, d"
|
||||
todo2.save!
|
||||
|
||||
tag_a_id = Tag.where(:name => "a").first.id
|
||||
tag_b_id = Tag.where(:name => "b").first.id
|
||||
tag_c_id = Tag.where(:name => "c").first.id
|
||||
|
||||
todos_with_aORc_and_b = Todo.with_tags([tag_a_id, tag_c_id]).with_tags([tag_b_id])
|
||||
assert_equal 1, todos_with_aORc_and_b.count
|
||||
assert_equal todo1.id, todos_with_aORc_and_b.first.id
|
||||
|
||||
# let todo2 fit the expression
|
||||
todo2.tag_list = "a, b, r"
|
||||
todo2.save!
|
||||
todos_with_aORc_and_b = Todo.with_tags([tag_a_id, tag_c_id]).with_tags([tag_b_id])
|
||||
assert_equal 2, todos_with_aORc_and_b.count
|
||||
end
|
||||
|
||||
# test named_scopes
|
||||
def test_find_completed
|
||||
# Given 2 completed todos, one completed now and one completed 2 months ago
|
||||
@not_completed1.toggle_completion!
|
||||
@completed.completed_at = 2.months.ago
|
||||
@completed.save!
|
||||
|
||||
completed_old = @completed
|
||||
completed_now = @not_completed1
|
||||
|
||||
# When I use the finders
|
||||
recent_completed_todos = Todo.completed_after(1.month.ago)
|
||||
older_completed_todos = Todo.completed_before(1.month.ago)
|
||||
|
||||
# Then completed1 should be before and completed2 should be after a month ago
|
||||
assert older_completed_todos.include?(completed_old)
|
||||
assert recent_completed_todos.include?(completed_now)
|
||||
|
||||
# And completed1 should not be after and completed2 should not be before a month ago
|
||||
assert !older_completed_todos.include?(completed_now)
|
||||
assert !recent_completed_todos.include?(completed_old)
|
||||
end
|
||||
|
||||
def test_find_created
|
||||
# Given 2 created todos, one created now and one created 2 months ago
|
||||
user = @completed.user
|
||||
todo_old = user.todos.create!({:description => "created long long ago", :context => @completed.context})
|
||||
todo_old.created_at = 2.months.ago
|
||||
todo_old.save!
|
||||
todo_now = user.todos.create!({:description => "just created", :context => @completed.context})
|
||||
|
||||
# When I use the finders
|
||||
recent_created_todos = Todo.created_after(1.month.ago)
|
||||
older_created_todos = Todo.created_before(1.month.ago)
|
||||
|
||||
# Then todo1 should be before and todo2 should be after a month ago
|
||||
assert older_created_todos.include?(todo_old)
|
||||
assert recent_created_todos.include?(todo_now)
|
||||
|
||||
# And todo1 should not be after and todo2 should not be before a month ago
|
||||
assert !older_created_todos.include?(todo_now)
|
||||
assert !recent_created_todos.include?(todo_old)
|
||||
end
|
||||
|
||||
def test_notes_are_rendered_on_save
|
||||
user = @completed.user
|
||||
todo = user.todos.create(:description => "test", :context => @completed.context)
|
||||
|
||||
assert_nil todo.notes
|
||||
assert_nil todo.rendered_notes
|
||||
|
||||
todo.notes = "*test*"
|
||||
todo.save!
|
||||
todo.reload
|
||||
|
||||
assert_equal "*test*", todo.notes
|
||||
assert_equal "<p><strong>test</strong></p>", todo.rendered_notes
|
||||
end
|
||||
|
||||
def test_from_rich_message_adds_to_default_context
|
||||
user = @completed.user
|
||||
default_context_id = @completed.context_id
|
||||
new_todo = Todo::from_rich_message(user, default_context_id, "new todo", "notes")
|
||||
|
||||
assert_not_nil new_todo
|
||||
assert_equal "new todo", new_todo.description
|
||||
assert_equal "notes", new_todo.notes
|
||||
assert_equal default_context_id, new_todo.context_id
|
||||
end
|
||||
|
||||
end
|
||||
396
test/models/user_test.rb
Normal file
396
test/models/user_test.rb
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
|
||||
class UserTest < ActiveSupport::TestCase
|
||||
fixtures :users, :preferences, :projects, :contexts, :todos, :recurring_todos
|
||||
|
||||
def setup
|
||||
assert_equal "test", ENV['RAILS_ENV']
|
||||
assert_equal "change-me", Tracks::Config.salt
|
||||
@admin_user = User.find(1)
|
||||
@other_user = User.find(2)
|
||||
end
|
||||
|
||||
# Test an admin user model
|
||||
#
|
||||
def test_admin
|
||||
assert_kind_of User, @admin_user
|
||||
assert_equal 1, @admin_user.id
|
||||
assert_equal "admin", @admin_user.login
|
||||
assert_not_nil @admin_user.crypted_password
|
||||
assert_not_nil @admin_user.token
|
||||
assert @admin_user.is_admin
|
||||
end
|
||||
|
||||
# Test a non-admin user model
|
||||
def test_non_admin
|
||||
assert_kind_of User, @other_user
|
||||
assert_equal 2, @other_user.id
|
||||
assert_equal "jane", @other_user.login
|
||||
assert_not_nil @other_user.crypted_password
|
||||
assert_not_nil @other_user.token
|
||||
assert @other_user.is_admin == false || @other_user.is_admin == 0
|
||||
end
|
||||
|
||||
# ============================================
|
||||
# Validations
|
||||
# ============================================
|
||||
|
||||
# Test a password shorter than 5 characters
|
||||
#
|
||||
def test_validate_short_password
|
||||
assert_no_difference 'User.count' do
|
||||
u = create_user :password => generate_random_string(4)
|
||||
assert_equal "is too short (minimum is 5 characters)", u.errors[:password][0]
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate_long_password
|
||||
assert_no_difference 'User.count' do
|
||||
u = create_user :password => generate_random_string(41)
|
||||
assert_equal "is too long (maximum is 40 characters)", u.errors[:password][0]
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate_correct_length_password
|
||||
assert_difference 'User.count' do
|
||||
create_user :password => generate_random_string(6)
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate_missing_password
|
||||
assert_no_difference 'User.count' do
|
||||
u = create_user :password => ''
|
||||
assert_equal ["can't be blank", "is too short (minimum is 5 characters)"], u.errors[:password]
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate_short_login
|
||||
assert_no_difference 'User.count' do
|
||||
u = create_user :login => 'ba'
|
||||
assert_equal "is too short (minimum is 3 characters)", u.errors[:login][0]
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate_long_login
|
||||
assert_no_difference 'User.count' do
|
||||
u = create_user :login => generate_random_string(81)
|
||||
assert_equal "is too long (maximum is 80 characters)", u.errors[:login][0]
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate_correct_length_login
|
||||
assert_difference 'User.count' do
|
||||
create_user :login => generate_random_string(6)
|
||||
end
|
||||
end
|
||||
|
||||
def test_validate_missing_login
|
||||
assert_no_difference 'User.count' do
|
||||
u = create_user :login => ''
|
||||
assert_equal ["can't be blank", "is too short (minimum is 3 characters)"], u.errors[:login]
|
||||
end
|
||||
end
|
||||
|
||||
def test_display_name_with_first_and_last_name_set
|
||||
@other_user.first_name = "Jane"
|
||||
@other_user.last_name = "Doe"
|
||||
assert_equal "Jane Doe", @other_user.display_name
|
||||
end
|
||||
|
||||
def test_display_name_with_first_name_set
|
||||
@other_user.first_name = "Jane"
|
||||
@other_user.last_name = nil
|
||||
assert_equal "Jane", @other_user.display_name
|
||||
end
|
||||
|
||||
def test_display_name_with_last_name_set
|
||||
@other_user.first_name = nil
|
||||
@other_user.last_name = "Doe"
|
||||
assert_equal "Doe", @other_user.display_name
|
||||
end
|
||||
|
||||
def test_display_name_with_neither_first_nor_last_name_set
|
||||
@other_user.first_name = nil
|
||||
@other_user.last_name = nil
|
||||
assert_equal @other_user.login, @other_user.display_name
|
||||
end
|
||||
|
||||
def test_prefs_is_short_for_preference
|
||||
assert_equal @admin_user.preference, @admin_user.prefs
|
||||
end
|
||||
|
||||
def test_to_param_returns_login
|
||||
assert_equal @admin_user.login, @admin_user.to_param
|
||||
end
|
||||
|
||||
def test_change_password
|
||||
assert_not_nil User.authenticate(@admin_user.login, "abracadabra")
|
||||
@admin_user.change_password("foobar", "foobar")
|
||||
@admin_user.reload
|
||||
assert_nil User.authenticate(@admin_user.login, "abracadabra")
|
||||
assert_not_nil User.authenticate(@admin_user.login, "foobar")
|
||||
end
|
||||
|
||||
def test_projects_next_project
|
||||
moremoney = projects(:moremoney)
|
||||
next_project = @admin_user.projects.next_from(moremoney)
|
||||
assert_equal projects(:gardenclean), next_project
|
||||
end
|
||||
|
||||
def test_projects_previous_project
|
||||
moremoney = projects(:moremoney)
|
||||
previous_project = @admin_user.projects.previous_from(moremoney)
|
||||
assert_equal projects(:timemachine), previous_project
|
||||
end
|
||||
|
||||
def test_projects_next_project_nil
|
||||
gardenclean = projects(:gardenclean)
|
||||
next_project = @admin_user.projects.next_from(gardenclean)
|
||||
assert_nil next_project
|
||||
end
|
||||
|
||||
def test_projects_previous_project_nil
|
||||
timemachine = projects(:timemachine)
|
||||
previous_project = @admin_user.projects.previous_from(timemachine)
|
||||
assert_nil previous_project
|
||||
end
|
||||
|
||||
def test_no_users_yet
|
||||
assert !User.no_users_yet?
|
||||
User.delete_all
|
||||
assert User.no_users_yet?
|
||||
end
|
||||
|
||||
def test_generate_token_updates_token
|
||||
assert_value_changed @admin_user, :token do
|
||||
@admin_user.send :generate_token
|
||||
end
|
||||
end
|
||||
|
||||
def test_find_admin
|
||||
assert_equal @admin_user, User.find_admin
|
||||
end
|
||||
|
||||
def test_validates_auth_type
|
||||
@other_user.auth_type = 'dnacheck'
|
||||
assert !@other_user.save
|
||||
assert_equal 1, @other_user.errors.count
|
||||
assert_equal ["not a valid authentication type (dnacheck)"], @other_user.errors[:auth_type]
|
||||
end
|
||||
|
||||
def test_find_context_by_params
|
||||
u = @admin_user
|
||||
c = u.contexts.find_by_params('id' => '1')
|
||||
assert_equal contexts(:agenda), c
|
||||
c = u.contexts.find_by_params('context_id' => '1')
|
||||
assert_equal contexts(:agenda), c
|
||||
end
|
||||
|
||||
def test_find_project_by_params
|
||||
u = @admin_user
|
||||
p = u.projects.find_by_params('id' => '1')
|
||||
assert_equal projects(:timemachine), p
|
||||
p = u.projects.find_by_params('project_id' => '1')
|
||||
assert_equal projects(:timemachine), p
|
||||
end
|
||||
|
||||
def test_update_project_positions
|
||||
assert_equal 1, Project.find(1).position
|
||||
assert_equal 2, Project.find(2).position
|
||||
assert_equal 3, Project.find(3).position
|
||||
|
||||
@admin_user.projects.update_positions([2,1,3])
|
||||
|
||||
assert_equal 2, Project.find(1).position
|
||||
assert_equal 1, Project.find(2).position
|
||||
assert_equal 3, Project.find(3).position
|
||||
end
|
||||
|
||||
def test_find_and_activate_deferred_todos_that_are_ready
|
||||
assert_equal 1, @admin_user.deferred_todos.count
|
||||
@admin_user.deferred_todos[0].show_from = Time.now.utc - 5.seconds
|
||||
@admin_user.deferred_todos[0].save
|
||||
@admin_user.deferred_todos.reload
|
||||
@admin_user.deferred_todos.find_and_activate_ready
|
||||
@admin_user.deferred_todos.reload
|
||||
assert_equal 0, @admin_user.deferred_todos.count
|
||||
end
|
||||
|
||||
def test_sort_active_projects_alphabetically
|
||||
u = users(:admin_user)
|
||||
u.projects.alphabetize(:state => "active")
|
||||
assert_equal 1, projects(:timemachine).position
|
||||
assert_equal 2, projects(:gardenclean).position
|
||||
assert_equal 3, projects(:moremoney).position
|
||||
end
|
||||
|
||||
def test_sort_active_projects_alphabetically_case_insensitive
|
||||
u = users(:admin_user)
|
||||
projects(:timemachine).name = projects(:timemachine).name.downcase
|
||||
projects(:timemachine).save!
|
||||
u.projects.alphabetize(:state => "active")
|
||||
assert_equal 1, projects(:timemachine).position
|
||||
assert_equal 2, projects(:gardenclean).position
|
||||
assert_equal 3, projects(:moremoney).position
|
||||
end
|
||||
|
||||
def test_should_create_user
|
||||
assert_difference 'User.count' do
|
||||
user = create_user
|
||||
assert !user.new_record?, "#{user.errors.full_messages.to_sentence}"
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_require_login
|
||||
assert_no_difference 'User.count' do
|
||||
u = create_user(:login => nil)
|
||||
assert u.errors[:login][0]
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_require_password
|
||||
assert_no_difference 'User.count' do
|
||||
u = create_user(:password => nil)
|
||||
assert u.errors[:password][0]
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_require_password_confirmation
|
||||
assert_no_difference 'User.count' do
|
||||
u = create_user(:password_confirmation => nil)
|
||||
assert u.errors[:password_confirmation][0]
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_reset_password
|
||||
users(:other_user).update_attributes(:password => 'new password', :password_confirmation => 'new password')
|
||||
assert_equal users(:other_user), User.authenticate('jane', 'new password')
|
||||
end
|
||||
|
||||
def test_should_not_rehash_password
|
||||
users(:other_user).update_attributes(:login => 'jane2')
|
||||
assert_equal users(:other_user), User.authenticate('jane2', 'sesame')
|
||||
end
|
||||
|
||||
def test_should_authenticate_user
|
||||
assert_equal users(:other_user), User.authenticate('jane', 'sesame')
|
||||
end
|
||||
|
||||
def test_should_set_remember_token
|
||||
users(:other_user).remember_me
|
||||
assert_not_nil users(:other_user).remember_token
|
||||
assert_not_nil users(:other_user).remember_token_expires_at
|
||||
end
|
||||
|
||||
def test_should_unset_remember_token
|
||||
users(:other_user).remember_me
|
||||
assert_not_nil users(:other_user).remember_token
|
||||
users(:other_user).forget_me
|
||||
assert_nil users(:other_user).remember_token
|
||||
end
|
||||
|
||||
def test_should_discover_using_depracted_password
|
||||
assert_nil @admin_user.uses_deprecated_password?
|
||||
assert_nil @other_user.uses_deprecated_password?
|
||||
assert users(:user_with_sha1_password).uses_deprecated_password?
|
||||
end
|
||||
|
||||
def test_should_not_have_deprecated_password_after_update
|
||||
u = users(:user_with_sha1_password)
|
||||
assert u.uses_deprecated_password?
|
||||
u.change_password("foobar", "foobar")
|
||||
assert_nil u.uses_deprecated_password?
|
||||
end
|
||||
|
||||
def test_should_authenticate_with_deprecated_password
|
||||
assert_nil User.authenticate('mr_deprecated', 'wrong password')
|
||||
assert_equal users(:user_with_sha1_password),
|
||||
User.authenticate('mr_deprecated', 'foobar')
|
||||
end
|
||||
|
||||
def test_password_matches
|
||||
assert_not_nil User.authenticate(@admin_user.login, "abracadabra")
|
||||
assert_nil User.authenticate(@admin_user.login, "incorrect")
|
||||
assert_not_nil User.authenticate(users(:user_with_sha1_password).login, "foobar")
|
||||
assert_nil User.authenticate(users(:user_with_sha1_password).login, "wrong")
|
||||
end
|
||||
|
||||
def test_update_positions_of_contexts
|
||||
u = users(:admin_user)
|
||||
assert_equal "1,2,3,4,5,6,7,8,9,12", u.contexts.map(&:id).join(",")
|
||||
|
||||
u.contexts.update_positions [1,2,3,8,9,12,4,5,6,7]
|
||||
assert_equal "1,2,3,8,9,12,4,5,6,7", u.contexts.reload.map(&:id).join(",")
|
||||
end
|
||||
|
||||
def test_cache_notes_count_for_projects
|
||||
u = users(:admin_user)
|
||||
u.projects.each do |p|
|
||||
assert_nil p.cached_note_count, "notes count should not be there"
|
||||
end
|
||||
|
||||
u.projects.cache_note_counts
|
||||
|
||||
u.projects.each do |p|
|
||||
assert !p.cached_note_count.nil?, "notes count should be there"
|
||||
end
|
||||
end
|
||||
|
||||
def test_actionize_projects
|
||||
u = users(:admin_user)
|
||||
assert_equal "1,2,3", u.projects.map(&:id).join(",")
|
||||
|
||||
u.projects.actionize
|
||||
|
||||
assert_equal "3,2,1", u.projects.reload.map(&:id).join(",")
|
||||
end
|
||||
|
||||
def test_remember_token
|
||||
u = users(:admin_user)
|
||||
assert_nil u.remember_token
|
||||
assert_nil u.remember_token_expires_at
|
||||
|
||||
# set token on 2013-feb-28
|
||||
Timecop.travel(Time.local(2013, 2, 28)) do
|
||||
u.remember_me
|
||||
assert_not_nil u.remember_token_expires_at
|
||||
|
||||
assert u.remember_token?
|
||||
end
|
||||
|
||||
# token should be valid after 5 days
|
||||
Timecop.travel(Time.local(2013, 3, 5)) do
|
||||
assert u.remember_token?
|
||||
end
|
||||
|
||||
# token should not be valid after more than 2 weeks
|
||||
Timecop.travel(Time.local(2013, 3, 28)) do
|
||||
assert !u.remember_token?
|
||||
end
|
||||
end
|
||||
|
||||
def test_count_todos_by_group
|
||||
u = users(:admin_user)
|
||||
|
||||
# test group counts for projects and contexts
|
||||
project_counts = u.todos.count_by_group(:project_id)
|
||||
assert_equal "6,3,4,4", project_counts.map{|pc|pc[1]}.join(",")
|
||||
|
||||
context_counts = u.todos.count_by_group(:context_id)
|
||||
assert_equal "7,3,1,3,1,2", context_counts.map{|cc|cc[1]}.join(",")
|
||||
|
||||
# add a todo to the first context and check that the count is increased
|
||||
u.todos.create!(:description => "yet another todo", :context => u.contexts.first)
|
||||
|
||||
context_counts = u.todos.reload.count_by_group(:context_id)
|
||||
assert_equal "8,3,1,3,1,2", context_counts.map{|cc|cc[1]}.join(",")
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def create_user(options = {})
|
||||
options[:password_confirmation] = options[:password] unless options.has_key?(:password_confirmation) || !options.has_key?(:password)
|
||||
User.create({ :login => 'quire', :password => 'quire', :password_confirmation => 'quire' }.merge(options))
|
||||
end
|
||||
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue