todolist_project 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/todolist_project.rb +152 -0
- data/test/todolist_project_test.rb +183 -0
- metadata +44 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 6d593e00021e6fa21566e654914f42d39fa66a2f
|
|
4
|
+
data.tar.gz: 6da49642516223bcbed99225602223f647409c6b
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e2179c3ee5d89990ec69363ef7bbd82f946d9601e7c889fa79bd27c593fe214b5ba12ffb900fecabe069b59cd24febc938b1fbad03f9051fcf16e909c0969fc9
|
|
7
|
+
data.tar.gz: af6cbdffb2da4538d1c5db111b2c68556cfa07799626453ab86ebc4abe236e957809c941ad99f78462a3d147a62efa78ee6a0584c0668c1223f81709acc966f4
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# This class represents a todo item and its associated
|
|
2
|
+
# data: name and description. There's also a "done"
|
|
3
|
+
# flag to show whether this todo item is done.
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
require 'stamp'
|
|
6
|
+
|
|
7
|
+
class Todo
|
|
8
|
+
DONE_MARKER = 'X'
|
|
9
|
+
UNDONE_MARKER = ' '
|
|
10
|
+
|
|
11
|
+
attr_accessor :title, :description, :done, :due_date
|
|
12
|
+
|
|
13
|
+
def initialize(title, description='')
|
|
14
|
+
@title = title
|
|
15
|
+
@description = description
|
|
16
|
+
@done = false
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def done!
|
|
20
|
+
self.done = true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def done?
|
|
24
|
+
done
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def undone!
|
|
28
|
+
self.done = false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_s # replaces original #to_s method
|
|
32
|
+
result = "[#{done? ? DONE_MARKER : UNDONE_MARKER}] #{title}"
|
|
33
|
+
result += due_date.stamp(' (Due: Friday January 6)') if due_date
|
|
34
|
+
result
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# This class represents a collection of Todo objects.
|
|
39
|
+
# You can perform typical collection-oriented actions
|
|
40
|
+
# on a TodoList object, including iteration and selection.
|
|
41
|
+
|
|
42
|
+
class TodoList
|
|
43
|
+
attr_accessor :title
|
|
44
|
+
|
|
45
|
+
def initialize(title)
|
|
46
|
+
@title = title
|
|
47
|
+
@todos = []
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def size
|
|
51
|
+
@todos.size
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def first
|
|
55
|
+
@todos.first
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def last
|
|
59
|
+
@todos.last
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def shift
|
|
63
|
+
@todos.shift
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def pop
|
|
67
|
+
@todos.pop
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def done?
|
|
71
|
+
@todos.all? { |todo| todo.done? }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def <<(todo)
|
|
75
|
+
raise TypeError, 'can only add Todo objects' unless todo.instance_of? Todo
|
|
76
|
+
|
|
77
|
+
@todos << todo
|
|
78
|
+
end
|
|
79
|
+
alias_method :add, :<<
|
|
80
|
+
|
|
81
|
+
def item_at(idx)
|
|
82
|
+
@todos.fetch(idx)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def mark_done_at(idx)
|
|
86
|
+
item_at(idx).done!
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def mark_undone_at(idx)
|
|
90
|
+
item_at(idx).undone!
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def done!
|
|
94
|
+
@todos.each_index do |idx|
|
|
95
|
+
mark_done_at(idx)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def remove_at(idx)
|
|
100
|
+
@todos.delete(item_at(idx))
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def to_s
|
|
104
|
+
text = "---- #{title} ----\n"
|
|
105
|
+
text << @todos.map(&:to_s).join("\n")
|
|
106
|
+
text
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def to_a
|
|
110
|
+
@todos
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def each
|
|
114
|
+
@todos.each do |todo|
|
|
115
|
+
yield(todo)
|
|
116
|
+
end
|
|
117
|
+
self
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def select
|
|
121
|
+
list = TodoList.new(title)
|
|
122
|
+
each do |todo|
|
|
123
|
+
list.add(todo) if yield(todo)
|
|
124
|
+
end
|
|
125
|
+
list
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# returns first Todo by title, or nil if no match
|
|
129
|
+
def find_by_title(title)
|
|
130
|
+
select { |todo| todo.title == title }.first
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def all_done
|
|
134
|
+
select { |todo| todo.done? }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def all_not_done
|
|
138
|
+
select { |todo| !todo.done? }
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def mark_done(title)
|
|
142
|
+
find_by_title(title) && find_by_title(title).done!
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def mark_all_done
|
|
146
|
+
each { |todo| todo.done! }
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def mark_all_undone
|
|
150
|
+
each { |todo| todo.undone! }
|
|
151
|
+
end
|
|
152
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
require 'bundler/setup'
|
|
2
|
+
require 'date'
|
|
3
|
+
require 'minitest/autorun'
|
|
4
|
+
require 'minitest/reporters'
|
|
5
|
+
Minitest::Reporters.use!
|
|
6
|
+
|
|
7
|
+
require_relative '../lib/todolist_project'
|
|
8
|
+
|
|
9
|
+
class TodoListTest < MiniTest::Test
|
|
10
|
+
def setup
|
|
11
|
+
@todo1 = Todo.new('Buy milk')
|
|
12
|
+
@todo2 = Todo.new('Clean room')
|
|
13
|
+
@todo3 = Todo.new('Go to gym')
|
|
14
|
+
@todos = [@todo1, @todo2, @todo3]
|
|
15
|
+
|
|
16
|
+
@list = TodoList.new("Today's Todos")
|
|
17
|
+
@list.add(@todo1)
|
|
18
|
+
@list.add(@todo2)
|
|
19
|
+
@list.add(@todo3)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_to_a
|
|
23
|
+
assert_equal(@todos, @list.to_a)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_add_raise_error
|
|
27
|
+
assert_raises(TypeError) { @list.add(1) }
|
|
28
|
+
assert_raises(TypeError) { @list.add('hi') }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_add_alias
|
|
32
|
+
new_todo = Todo.new('Walk the dog')
|
|
33
|
+
@list.add(new_todo)
|
|
34
|
+
todos = @todos << new_todo
|
|
35
|
+
|
|
36
|
+
assert_equal(todos, @list.to_a)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_size
|
|
40
|
+
assert_equal(3, @list.size)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_first
|
|
44
|
+
assert_equal(@todo1, @list.first)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_last
|
|
48
|
+
assert_equal(@todo3, @list.last)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_shift
|
|
52
|
+
todo = @list.shift
|
|
53
|
+
assert_equal(@todo1, todo)
|
|
54
|
+
assert_equal([@todo2, @todo3], @list.to_a)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_pop
|
|
58
|
+
todo = @list.pop
|
|
59
|
+
assert_equal(@todo3, todo)
|
|
60
|
+
assert_equal([@todo1, @todo2], @list.to_a)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_done_question
|
|
64
|
+
assert_equal(false, @list.done?)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def test_item_at
|
|
68
|
+
assert_raises(IndexError) { @list.item_at(100) }
|
|
69
|
+
assert_equal(@todo1, @list.item_at(0))
|
|
70
|
+
assert_equal(@todo2, @list.item_at(1))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_mark_done_at
|
|
74
|
+
assert_raises(IndexError) { @list.mark_done_at(100) }
|
|
75
|
+
@list.mark_done_at(1)
|
|
76
|
+
assert_equal(false, @todo1.done?)
|
|
77
|
+
assert_equal(true, @todo2.done?)
|
|
78
|
+
assert_equal(false, @todo3.done?)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_mark_undone_at
|
|
82
|
+
assert_raises(IndexError) { @list.mark_undone_at(100) }
|
|
83
|
+
@todo1.done!
|
|
84
|
+
@todo2.done!
|
|
85
|
+
@todo3.done!
|
|
86
|
+
|
|
87
|
+
@list.mark_undone_at(1)
|
|
88
|
+
|
|
89
|
+
assert_equal(true, @todo1.done?)
|
|
90
|
+
assert_equal(false, @todo2.done?)
|
|
91
|
+
assert_equal(true, @todo3.done?)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_done_bang
|
|
95
|
+
@list.done!
|
|
96
|
+
assert_equal(true, @todo1.done?)
|
|
97
|
+
assert_equal(true, @todo2.done?)
|
|
98
|
+
assert_equal(true, @todo3.done?)
|
|
99
|
+
assert_equal(true, @list.done?)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def test_remove_at
|
|
103
|
+
assert_raises(IndexError) { @list.remove_at(100) }
|
|
104
|
+
@list.remove_at(1)
|
|
105
|
+
assert_equal([@todo1, @todo3], @list.to_a)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def test_to_s
|
|
109
|
+
output = <<-OUTPUT.chomp.gsub(/^\s+/, '')
|
|
110
|
+
---- Today's Todos ----
|
|
111
|
+
[ ] Buy milk
|
|
112
|
+
[ ] Clean room
|
|
113
|
+
[ ] Go to gym
|
|
114
|
+
OUTPUT
|
|
115
|
+
|
|
116
|
+
assert_equal(output, @list.to_s)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def test_to_s_2
|
|
120
|
+
output = <<-OUTPUT.chomp.gsub(/^\s+/, '')
|
|
121
|
+
---- Today's Todos ----
|
|
122
|
+
[ ] Buy milk
|
|
123
|
+
[X] Clean room
|
|
124
|
+
[ ] Go to gym
|
|
125
|
+
OUTPUT
|
|
126
|
+
|
|
127
|
+
@list.mark_done_at(1)
|
|
128
|
+
assert_equal(output, @list.to_s)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def test_to_s_3
|
|
132
|
+
output = <<-OUTPUT.chomp.gsub(/^\s+/, '')
|
|
133
|
+
---- Today's Todos ----
|
|
134
|
+
[X] Buy milk
|
|
135
|
+
[X] Clean room
|
|
136
|
+
[X] Go to gym
|
|
137
|
+
OUTPUT
|
|
138
|
+
|
|
139
|
+
@list.done!
|
|
140
|
+
assert_equal(output, @list.to_s)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def test_each
|
|
144
|
+
result = []
|
|
145
|
+
@list.each { |todo| result << todo }
|
|
146
|
+
assert_equal([@todo1, @todo2, @todo3], result)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def test_each_returns_original_list
|
|
150
|
+
assert_equal(@list, @list.each {|todo| nil })
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def test_select
|
|
154
|
+
@todo1.done!
|
|
155
|
+
list = TodoList.new(@list.title)
|
|
156
|
+
list.add(@todo1)
|
|
157
|
+
|
|
158
|
+
assert_equal(list.title, @list.title)
|
|
159
|
+
assert_equal(list.to_s, @list.select{ |todo| todo.done? }.to_s)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def test_no_due_date
|
|
163
|
+
assert_nil(@todo1.due_date)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def test_due_date
|
|
167
|
+
due_date = Date.today + 3
|
|
168
|
+
@todo2.due_date = due_date
|
|
169
|
+
assert(@todo2.due_date, due_date)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def test_to_s_with_due_date
|
|
173
|
+
@todo2.due_date = Date.new(2017, 4, 15)
|
|
174
|
+
output = <<-OUTPUT.chomp.gsub(/^\s+/, '')
|
|
175
|
+
---- Today's Todos ----
|
|
176
|
+
[ ] Buy milk
|
|
177
|
+
[ ] Clean room (Due: Saturday April 15)
|
|
178
|
+
[ ] Go to gym
|
|
179
|
+
OUTPUT
|
|
180
|
+
|
|
181
|
+
assert_equal(output, @list.to_s)
|
|
182
|
+
end
|
|
183
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: todolist_project
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Pete Williams
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-04-01 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: This is a simple todo list manager!
|
|
14
|
+
email: pw@example.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- lib/todolist_project.rb
|
|
20
|
+
- test/todolist_project_test.rb
|
|
21
|
+
homepage: http://example.com/todolist_project
|
|
22
|
+
licenses: []
|
|
23
|
+
metadata: {}
|
|
24
|
+
post_install_message:
|
|
25
|
+
rdoc_options: []
|
|
26
|
+
require_paths:
|
|
27
|
+
- lib
|
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
34
|
+
requirements:
|
|
35
|
+
- - ">="
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: '0'
|
|
38
|
+
requirements: []
|
|
39
|
+
rubyforge_project:
|
|
40
|
+
rubygems_version: 2.6.7
|
|
41
|
+
signing_key:
|
|
42
|
+
specification_version: 4
|
|
43
|
+
summary: Todo List Manager!
|
|
44
|
+
test_files: []
|