Skip to content

Commit

Permalink
Merge pull request #26 from ScottGarman/add-more-model-tests
Browse files Browse the repository at this point in the history
Update models and add unit tests
  • Loading branch information
ScottGarman authored Jan 3, 2025
2 parents f5d8ac8 + 0517dfd commit 5b787e7
Show file tree
Hide file tree
Showing 7 changed files with 372 additions and 13 deletions.
9 changes: 9 additions & 0 deletions app/models/quote.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
class Quote < ApplicationRecord
belongs_to :user

# Validation
validates_presence_of :user_id

validates :quotation, presence: true,
length: { maximum: 255 }

validates :source, presence: true,
length: { maximum: 255 }
end
109 changes: 109 additions & 0 deletions app/models/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,113 @@ class Task < ApplicationRecord
scope :incomplete, -> { where(status: :INCOMPLETE) }
scope :completed, -> { where(status: :COMPLETED) }
scope :no_due_date, -> { where("due_at IS NULL") }

def self.category(tc_id)
where(task_category_id: tc_id)
end

# Reassign a task collection to a different Task Category
def self.move_to_category(tc_id)
update_all(task_category_id: tc_id)
end

# today_db should be today's date in database format (yyyy-mm-dd). It's
# passed as an argument to allow its caller to apply the user's time
# zone to the date.
#
# Current tasks are due today or before, or have no due date set
def self.current(today_db)
incomplete.where("due_at <= ?", today_db)
.order(due_at: :asc, priority: :asc) +
incomplete.no_due_date.order(priority: :asc)
end

# today_db should be today's date in database format (yyyy-mm-dd). It's
# passed as an argument to allow its caller to apply the user's time
# zone to the date.
def self.current_with_due_dates(today_db)
incomplete.where("due_at <= ?", today_db)
.order(due_at: :asc, priority: :asc)
end

# Boolean method that returns whether the task is "current", i.e. would be
# displayed in the Current Tasks tab (instead of Upcoming Tasks). today_db
# should be today's date in database format (yyyy-mm-dd). It's passed as an
# argument to allow its caller to apply the user's time zone to the date.
def current?(today_db)
due_at.to_s <= today_db || due_at.nil?
end

# Boolean method that returns whether the task is "upcoming", i.e. would be
# displayed in the Upcoming Tasks tab (instead of Current Tasks). today_db
# should be today's date in database format (yyyy-mm-dd). It's passed as an
# argument to allow its caller to apply the user's time zone to the date.
def upcoming?(today_db)
due_at.to_s > today_db
end

# today_db should be today's date in database format (yyyy-mm-dd). It's
# passed as an arguent to allow its caller to apply the user's time
# zone to the date.
def self.overdue(today_db)
incomplete.where("due_at < ?", today_db).order(due_at: :asc, priority: :asc)
end

# today_db should be today's date in database format (yyyy-mm-dd). It's
# passed as an argument to allow its caller to apply the user's time
# zone to the date.
def self.future(today_db)
incomplete.where("due_at > ?", today_db).order(due_at: :asc, priority: :asc)
end

# today_start_db and today_end_db should be DateTimes of the start and
# end of today. They are passed as arguments to allow its caller to
# apply the user's time zone to the dates.
def self.completed_today(today_start_db, today_end_db)
completed.where("completed_at BETWEEN ? AND ?", today_start_db,
today_end_db).order(due_at: :asc, priority: :asc)
end

def self.search(summary_terms, completed_status, category_id, sort_by)
logger.info("*** Task.search(): args are [#{summary_terms}], " \
"[#{completed_status}], and [#{category_id}]")

tasks = all
summary_terms && tasks = tasks.where("summary LIKE ?", "%#{summary_terms}%")
tasks = tasks.completed if completed_status == "completed"
tasks = tasks.incomplete if completed_status == "incomplete"
tasks = tasks.category(category_id) if category_id != "All"

return tasks.order("due_at asc") if sort_by.nil?

# customize the sort order
return tasks.order(due_at: :asc) if sort_by == "due-date-asc"
return tasks.order(due_at: :desc) if sort_by == "due-date-desc"
return tasks.order(priority: :asc) if sort_by == "priority-asc"
return tasks.order(priority: :desc) if sort_by == "priority-desc"

# if we've reached this point, something isn't right (a malicious user may
# be messing with the sort_by string), so to prevent a site crash, just
# return an empty array
[]
end

# Returns a boolean based on the tasks' status: INCOMPLETE as false,
# COMPLETED as true
def status_as_boolean
return false if status == "INCOMPLETE"
return true if status == "COMPLETED"

false
end

def toggle_status
if status == "INCOMPLETE"
update_attribute(:status, "COMPLETED")
update_attribute(:completed_at, Time.now)
else
update_attribute(:status, "INCOMPLETE")
update_attribute(:completed_at, nil)
end
end
end
55 changes: 52 additions & 3 deletions test/models/quote_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,56 @@
require "test_helper"

class QuoteTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
def setup
@user = User.new(first_name: "Bubba",
last_name: "Jones",
email_address: "bubbajones@example.com",
password: "foobarbaz12345",
password_confirmation: "foobarbaz12345")
@user.save!

@quote = Quote.new(quotation: "Sample Quotation", source: "Source")
end

test "should be valid" do
@user.quotes << @quote
assert @quote.valid?
end

test "quotation must be associated with a User" do
assert @quote.invalid?
assert @quote.errors[:user_id].any?
end

test "quotation should be present and not empty" do
@quote.quotation = " "
assert @quote.invalid?
assert @quote.errors[:quotation].any?
end

test "source should be present and not empty" do
@quote.source = " "
assert @quote.invalid?
assert @quote.errors[:source].any?
end

test "quotation should not be too long" do
@user.quotes << @quote
@quote.quotation = "a" * 256
assert @quote.invalid?
assert @quote.errors[:quotation].any?

@quote.quotation = "a" * 255
assert @quote.valid?
end

test "source should not be too long" do
@user.quotes << @quote
@quote.source = "a" * 256
assert @quote.invalid?
assert @quote.errors[:source].any?

@quote.source = "a" * 255
assert @quote.valid?
end
end
24 changes: 21 additions & 3 deletions test/models/setting_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
require "test_helper"

class SettingTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
def setup
@user = User.new(first_name: "Bubba",
last_name: "Jones",
email_address: "bubbajones@example.com",
password: "foobarbaz12345",
password_confirmation: "foobarbaz12345")
@user.save!

@setting = Setting.new
end

test "setting must be associated with a User" do
assert @setting.invalid?
assert @setting.errors[:user_id].any?

# The User model generates a default setting when it was created
assert @user.setting.valid?

@user.setting = @setting
assert @setting.valid?
end
end
51 changes: 48 additions & 3 deletions test/models/task_category_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,52 @@
require "test_helper"

class TaskCategoryTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
def setup
@user = User.new(first_name: "Bubba",
last_name: "Jones",
email_address: "bubbajones@example.com",
password: "foobarbaz12345",
password_confirmation: "foobarbaz12345")
@user.save!

@tc = TaskCategory.new(name: "Work")
end

test "should be valid" do
@user.task_categories << @tc
assert @tc.valid?
end

test "a TaskCategory must be associated with a User" do
assert @tc.invalid?
assert @tc.errors[:user_id].any?
end

test "name should be present and not empty" do
@user.task_categories << @tc
@tc.name = " "
assert @tc.invalid?
assert @tc.errors[:name].any?
end

test "name should not be too long" do
@user.task_categories << @tc
@tc.name = "a" * 51
assert @tc.invalid?
assert @tc.errors[:name].any?

@tc.name = "a" * 50
assert @tc.valid?
end

test "duplicate TaskCategory names cannot exist for the same User" do
@user.task_categories << @tc
assert_not_nil @user.task_categories.find_by_name("Work")

tc2 = TaskCategory.new(name: "Work")
assert_equal @user.task_categories.count, 2
@user.task_categories << tc2
assert tc2.invalid?
assert tc2.errors[:name].any?
end
end
Loading

0 comments on commit 5b787e7

Please sign in to comment.