Commit e167f285 authored by Robert Speicher's avatar Robert Speicher

Update Taskable to use TaskList

parent ce29e5cd
require 'task_list'
# Contains functionality for objects that can have task lists in their # Contains functionality for objects that can have task lists in their
# descriptions. Task list items can be added with Markdown like "* [x] Fix # descriptions. Task list items can be added with Markdown like "* [x] Fix
# bugs". # bugs".
# #
# Used by MergeRequest and Issue # Used by MergeRequest and Issue
module Taskable module Taskable
TASK_PATTERN_MD = /^(?<bullet> *[*-] *)\[(?<checked>[ xX])\]/.freeze # Called by `TaskList::Summary`
TASK_PATTERN_HTML = /^<li>(?<p_tag>\s*<p>)?\[(?<checked>[ xX])\]/.freeze def task_list_items
return [] if description.blank?
# Change the state of a task list item for this Taskable. Edit the object's
# description by finding the nth task item and changing its checkbox
# placeholder to "[x]" if +checked+ is true, or "[ ]" if it's false.
# Note: task numbering starts with 1
def update_nth_task(n, checked)
index = 0
check_char = checked ? 'x' : ' '
# Do this instead of using #gsub! so that ActiveRecord detects that a field @task_list_items ||= description.scan(TaskList::Filter::ItemPattern).collect do |item|
# has changed. # ItemPattern strips out the hyphen, but Item requires it. Rabble rabble.
self.description = self.description.gsub(TASK_PATTERN_MD) do |match| TaskList::Item.new("- #{item}")
index += 1
case index
when n then "#{$LAST_MATCH_INFO[:bullet]}[#{check_char}]"
else match
end
end end
end
save def tasks
@tasks ||= TaskList.new(self)
end end
# Return true if this object's description has any task list items. # Return true if this object's description has any task list items.
def tasks? def tasks?
description && description.match(TASK_PATTERN_MD) tasks.summary.items?
end end
# Return a string that describes the current state of this Taskable's task # Return a string that describes the current state of this Taskable's task
# list items, e.g. "20 tasks (12 done, 8 unfinished)" # list items, e.g. "20 tasks (12 done, 8 unfinished)"
def task_status def task_status
return nil unless description return '' if description.blank?
num_tasks = 0
num_done = 0
description.scan(TASK_PATTERN_MD) do
num_tasks += 1
num_done += 1 unless $LAST_MATCH_INFO[:checked] == ' '
end
"#{num_tasks} tasks (#{num_done} done, #{num_tasks - num_done} unfinished)" sum = tasks.summary
"#{sum.item_count} tasks (#{sum.complete_count} done, #{sum.incomplete_count} unfinished)"
end end
end end
...@@ -4,27 +4,13 @@ ...@@ -4,27 +4,13 @@
# subject { Issue or MergeRequest } # subject { Issue or MergeRequest }
shared_examples 'a Taskable' do shared_examples 'a Taskable' do
before do before do
subject.description = <<EOT.gsub(/ {6}/, '') subject.description = <<-EOT.strip_heredoc
* [ ] Task 1 * [ ] Task 1
* [x] Task 2 * [x] Task 2
* [x] Task 3 * [x] Task 3
* [ ] Task 4 * [ ] Task 4
* [ ] Task 5 * [ ] Task 5
EOT EOT
end
it 'updates the Nth task correctly' do
subject.update_nth_task(1, true)
expect(subject.description).to match(/\[x\] Task 1/)
subject.update_nth_task(2, true)
expect(subject.description).to match('\[x\] Task 2')
subject.update_nth_task(3, false)
expect(subject.description).to match('\[ \] Task 3')
subject.update_nth_task(4, false)
expect(subject.description).to match('\[ \] Task 4')
end end
it 'returns the correct task status' do it 'returns the correct task status' do
...@@ -33,10 +19,14 @@ EOT ...@@ -33,10 +19,14 @@ EOT
expect(subject.task_status).to match('3 unfinished') expect(subject.task_status).to match('3 unfinished')
end end
it 'knows if it has tasks' do describe '#tasks?' do
expect(subject.tasks?).to be_truthy it 'returns true when object has tasks' do
expect(subject.tasks?).to eq true
end
subject.description = 'Now I have no tasks' it 'returns false when object has no tasks' do
expect(subject.tasks?).to be_falsey subject.description = 'Now I have no tasks'
expect(subject.tasks?).to eq false
end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment