friends 0.28 → 0.29
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 +4 -4
- data/.rubocop.yml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +2 -0
- data/CHANGELOG.md +13 -0
- data/README.md +35 -5
- data/Rakefile +1 -1
- data/bin/friends +7 -379
- data/friends.gemspec +3 -1
- data/lib/friends/activity.rb +4 -4
- data/lib/friends/commands/add.rb +64 -0
- data/lib/friends/commands/clean.rb +9 -0
- data/lib/friends/commands/edit.rb +12 -0
- data/lib/friends/commands/graph.rb +56 -0
- data/lib/friends/commands/list.rb +143 -0
- data/lib/friends/commands/remove.rb +27 -0
- data/lib/friends/commands/rename.rb +30 -0
- data/lib/friends/commands/set.rb +14 -0
- data/lib/friends/commands/stats.rb +11 -0
- data/lib/friends/commands/suggest.rb +20 -0
- data/lib/friends/commands/update.rb +29 -0
- data/lib/friends/graph.rb +7 -7
- data/lib/friends/introvert.rb +23 -18
- data/lib/friends/version.rb +1 -1
- data/test/commands/add/activity_spec.rb +379 -0
- data/test/commands/add/friend_spec.rb +30 -0
- data/test/commands/add/location_spec.rb +30 -0
- data/test/commands/add/nickname_spec.rb +50 -0
- data/test/commands/add/tag_spec.rb +65 -0
- data/test/commands/clean_spec.rb +39 -0
- data/test/commands/graph_spec.rb +147 -0
- data/test/commands/help_spec.rb +45 -0
- data/test/commands/list/activities_spec.rb +136 -0
- data/test/commands/list/favorite/friends_spec.rb +77 -0
- data/test/commands/list/favorite/locations_spec.rb +82 -0
- data/test/commands/list/friends_spec.rb +76 -0
- data/test/commands/list/locations_spec.rb +35 -0
- data/test/commands/list/tags_spec.rb +58 -0
- data/test/commands/remove/nickname_spec.rb +63 -0
- data/test/commands/remove/tag_spec.rb +64 -0
- data/test/commands/rename/friend_spec.rb +55 -0
- data/test/commands/rename/location_spec.rb +43 -0
- data/test/commands/set/location_spec.rb +54 -0
- data/test/commands/stats_spec.rb +41 -0
- data/test/commands/suggest_spec.rb +86 -0
- data/test/commands/update_spec.rb +13 -0
- data/test/helper.rb +114 -0
- metadata +89 -15
- data/test/activity_spec.rb +0 -597
- data/test/friend_spec.rb +0 -241
- data/test/graph_spec.rb +0 -92
- data/test/introvert_spec.rb +0 -969
- data/test/location_spec.rb +0 -60
data/test/friend_spec.rb
DELETED
@@ -1,241 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "./test/helper"
|
4
|
-
|
5
|
-
describe Friends::Friend do
|
6
|
-
let(:friend_name) { "Jacob Evelyn" }
|
7
|
-
let(:friend) { Friends::Friend.new(name: friend_name) }
|
8
|
-
|
9
|
-
describe ".deserialize" do
|
10
|
-
subject { Friends::Friend.deserialize(serialized_str) }
|
11
|
-
|
12
|
-
describe "when string is well-formed" do
|
13
|
-
let(:serialized_str) do
|
14
|
-
"#{Friends::Friend::SERIALIZATION_PREFIX}#{friend_name}"
|
15
|
-
end
|
16
|
-
|
17
|
-
it "creates a friend with the correct name" do
|
18
|
-
subject.name.must_equal friend_name
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe "when string is malformed" do
|
23
|
-
let(:serialized_str) { "" }
|
24
|
-
|
25
|
-
it { proc { subject }.must_raise Serializable::SerializationError }
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "when string has one nickname" do
|
29
|
-
let(:serialized_str) { "Guybrush Threepwood (a.k.a. Brush)" }
|
30
|
-
it { subject.name.must_equal "Guybrush Threepwood" }
|
31
|
-
it { subject.instance_variable_get(:@nicknames).must_equal ["Brush"] }
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "when string has multiple nicknames" do
|
35
|
-
let(:serialized_str) { "Guybrush Threepwood (a.k.a. Brush a.k.a. Guy)" }
|
36
|
-
it { subject.name.must_equal "Guybrush Threepwood" }
|
37
|
-
it do
|
38
|
-
subject.instance_variable_get(:@nicknames).must_equal ["Brush", "Guy"]
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "when string has a location" do
|
43
|
-
let(:serialized_str) { "Guybrush Threepwood [Plunder Island]" }
|
44
|
-
it { subject.name.must_equal "Guybrush Threepwood" }
|
45
|
-
it { subject.location_name.must_equal "Plunder Island" }
|
46
|
-
end
|
47
|
-
|
48
|
-
describe "when string has one tag" do
|
49
|
-
let(:serialized_str) { "Guybrush Threepwood @pirate" }
|
50
|
-
it { subject.name.must_equal "Guybrush Threepwood" }
|
51
|
-
it { subject.tags.must_equal ["@pirate"] }
|
52
|
-
end
|
53
|
-
|
54
|
-
describe "when string has multiple tags" do
|
55
|
-
let(:serialized_str) { "Guybrush Threepwood @pirate @swashbuckler" }
|
56
|
-
it { subject.name.must_equal "Guybrush Threepwood" }
|
57
|
-
it { subject.tags.must_equal ["@pirate", "@swashbuckler"] }
|
58
|
-
end
|
59
|
-
|
60
|
-
describe "when string has nicknames and tags" do
|
61
|
-
let(:serialized_str) do
|
62
|
-
"Guybrush Threepwood (a.k.a. Brush a.k.a. Guy) @pirate @swashbuckler"
|
63
|
-
end
|
64
|
-
it { subject.name.must_equal "Guybrush Threepwood" }
|
65
|
-
it do
|
66
|
-
subject.instance_variable_get(:@nicknames).must_equal ["Brush", "Guy"]
|
67
|
-
end
|
68
|
-
it { subject.tags.must_equal ["@pirate", "@swashbuckler"] }
|
69
|
-
end
|
70
|
-
|
71
|
-
describe "when string has nicknames and a location" do
|
72
|
-
let(:serialized_str) do
|
73
|
-
"Guybrush Threepwood (a.k.a. Brush a.k.a. Guy) [Plunder Island]"
|
74
|
-
end
|
75
|
-
it { subject.name.must_equal "Guybrush Threepwood" }
|
76
|
-
it do
|
77
|
-
subject.instance_variable_get(:@nicknames).must_equal ["Brush", "Guy"]
|
78
|
-
end
|
79
|
-
it { subject.location_name.must_equal "Plunder Island" }
|
80
|
-
end
|
81
|
-
|
82
|
-
describe "when string has a location and tags" do
|
83
|
-
let(:serialized_str) do
|
84
|
-
"Guybrush Threepwood [Plunder Island] @pirate @swashbuckler"
|
85
|
-
end
|
86
|
-
it { subject.name.must_equal "Guybrush Threepwood" }
|
87
|
-
it { subject.location_name.must_equal "Plunder Island" }
|
88
|
-
it { subject.tags.must_equal ["@pirate", "@swashbuckler"] }
|
89
|
-
end
|
90
|
-
|
91
|
-
describe "when string has nicknames, a location, and tags" do
|
92
|
-
let(:serialized_str) do
|
93
|
-
"Guybrush Threepwood (a.k.a. Brush a.k.a. Guy) [Plunder Island] "\
|
94
|
-
"@pirate @swashbuckler"
|
95
|
-
end
|
96
|
-
it { subject.name.must_equal "Guybrush Threepwood" }
|
97
|
-
it do
|
98
|
-
subject.instance_variable_get(:@nicknames).must_equal ["Brush", "Guy"]
|
99
|
-
end
|
100
|
-
it { subject.location_name.must_equal "Plunder Island" }
|
101
|
-
it { subject.tags.must_equal ["@pirate", "@swashbuckler"] }
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
describe "#new" do
|
106
|
-
subject { friend }
|
107
|
-
|
108
|
-
it { subject.name.must_equal friend_name }
|
109
|
-
end
|
110
|
-
|
111
|
-
describe "#serialize" do
|
112
|
-
subject { friend.serialize }
|
113
|
-
|
114
|
-
it do
|
115
|
-
subject.must_equal(
|
116
|
-
"#{Friends::Friend::SERIALIZATION_PREFIX}#{friend_name}"
|
117
|
-
)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
describe "#add_nickname" do
|
122
|
-
subject { friend.add_nickname("The Dude") }
|
123
|
-
|
124
|
-
it "adds the nickname" do
|
125
|
-
subject
|
126
|
-
friend.instance_variable_get(:@nicknames).must_include("The Dude")
|
127
|
-
end
|
128
|
-
|
129
|
-
it "does not keep duplicates" do
|
130
|
-
# Add the same nickname twice. Do not use `subject` because it's memoized.
|
131
|
-
friend.add_nickname("The Dude")
|
132
|
-
friend.add_nickname("The Dude")
|
133
|
-
|
134
|
-
friend.instance_variable_get(:@nicknames).must_equal ["The Dude"]
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
describe "#remove_nickname" do
|
139
|
-
subject { friend.remove_nickname("Jake") }
|
140
|
-
|
141
|
-
describe "when the nickname is present" do
|
142
|
-
let(:friend) do
|
143
|
-
Friends::Friend.new(name: friend_name, nickname_str: "Jake")
|
144
|
-
end
|
145
|
-
|
146
|
-
it "removes the nickname" do
|
147
|
-
friend.instance_variable_get(:@nicknames).must_equal ["Jake"]
|
148
|
-
subject
|
149
|
-
friend.instance_variable_get(:@nicknames).must_equal []
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
describe "when the nickname is not present" do
|
154
|
-
it "raises an error if the nickname is not found" do
|
155
|
-
proc { subject }.must_raise Friends::FriendsError
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
describe "#add_tag" do
|
161
|
-
subject { friend.add_tag("@college") }
|
162
|
-
|
163
|
-
it "adds the nickname" do
|
164
|
-
subject
|
165
|
-
friend.tags.must_include("@college")
|
166
|
-
end
|
167
|
-
|
168
|
-
it "does not keep duplicates" do
|
169
|
-
# Add the same nickname twice. Do not use `subject` because it's memoized.
|
170
|
-
friend.add_tag("@college")
|
171
|
-
friend.add_tag("@college")
|
172
|
-
|
173
|
-
friend.tags.must_equal ["@college"]
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
describe "@remove_tag" do
|
178
|
-
subject { friend.remove_tag("@school") }
|
179
|
-
|
180
|
-
describe "when the tag is present" do
|
181
|
-
let(:friend) do
|
182
|
-
Friends::Friend.new(name: friend_name, tags_str: "@school @work")
|
183
|
-
end
|
184
|
-
|
185
|
-
it "removes the nickname" do
|
186
|
-
friend.instance_variable_get(:@tags).must_equal ["@school", "@work"]
|
187
|
-
subject
|
188
|
-
friend.instance_variable_get(:@tags).must_equal ["@work"]
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
describe "when the nickname is not present" do
|
193
|
-
it "raises an error if the nickname is not found" do
|
194
|
-
proc { subject }.must_raise Friends::FriendsError
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
describe "#n_activities" do
|
200
|
-
subject { friend.n_activities }
|
201
|
-
|
202
|
-
it "defaults to zero" do
|
203
|
-
subject.must_equal 0
|
204
|
-
end
|
205
|
-
|
206
|
-
it "is writable" do
|
207
|
-
friend.n_activities += 1
|
208
|
-
subject.must_equal 1
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
describe "#likelihood_score" do
|
213
|
-
subject { friend.likelihood_score }
|
214
|
-
|
215
|
-
it "defaults to zero" do
|
216
|
-
subject.must_equal 0
|
217
|
-
end
|
218
|
-
|
219
|
-
it "is writable" do
|
220
|
-
friend.likelihood_score += 1
|
221
|
-
subject.must_equal 1
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
describe "#regexes_for_name" do
|
226
|
-
subject { friend.regexes_for_name }
|
227
|
-
|
228
|
-
it "generates appropriate regexes" do
|
229
|
-
subject.any? { |r| r =~ friend_name }.must_equal true
|
230
|
-
subject.any? { |r| r =~ friend_name.partition(" ").first }.must_equal true
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
describe "#<=>" do
|
235
|
-
it "sorts alphabetically" do
|
236
|
-
aaron = Friends::Friend.new(name: "Aaron")
|
237
|
-
zeke = Friends::Friend.new(name: "Zeke")
|
238
|
-
[zeke, aaron].sort.must_equal [aaron, zeke]
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
data/test/graph_spec.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "./test/helper"
|
3
|
-
|
4
|
-
describe Friends::Graph do
|
5
|
-
subject do
|
6
|
-
Friends::Graph.new(
|
7
|
-
start_date: start_date,
|
8
|
-
end_date: end_date,
|
9
|
-
activities: activities
|
10
|
-
).to_h
|
11
|
-
end
|
12
|
-
|
13
|
-
let(:start_date) { Date.new(2016, 1, 1) }
|
14
|
-
let(:end_date) { Date.new(2016, 2, 1) }
|
15
|
-
let(:activities) do
|
16
|
-
[
|
17
|
-
Friends::Activity.new(
|
18
|
-
str: "2016-02-01: Relaxing."
|
19
|
-
),
|
20
|
-
|
21
|
-
Friends::Activity.new(
|
22
|
-
str: "2016-01-01: Running."
|
23
|
-
)
|
24
|
-
]
|
25
|
-
end
|
26
|
-
|
27
|
-
it "graphs activities by month" do
|
28
|
-
subject.must_equal(
|
29
|
-
"Jan 2016" => 1,
|
30
|
-
"Feb 2016" => 1
|
31
|
-
)
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "there is a gap between activities" do
|
35
|
-
let(:end_date) { Date.new(2016, 3, 1) }
|
36
|
-
|
37
|
-
let(:activities) do
|
38
|
-
[
|
39
|
-
Friends::Activity.new(
|
40
|
-
str: "2016-03-01: Relaxing."
|
41
|
-
),
|
42
|
-
|
43
|
-
Friends::Activity.new(
|
44
|
-
str: "2016-01-01: Running."
|
45
|
-
)
|
46
|
-
]
|
47
|
-
end
|
48
|
-
|
49
|
-
it "includes the month with no activities" do
|
50
|
-
subject.must_equal(
|
51
|
-
"Jan 2016" => 1,
|
52
|
-
"Feb 2016" => 0,
|
53
|
-
"Mar 2016" => 1
|
54
|
-
)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe "graph starts before the first activity" do
|
59
|
-
let(:start_date) { Date.new(2015, 12, 1) }
|
60
|
-
|
61
|
-
it "graphs activities by month" do
|
62
|
-
subject.must_equal(
|
63
|
-
"Dec 2015" => 0,
|
64
|
-
"Jan 2016" => 1,
|
65
|
-
"Feb 2016" => 1
|
66
|
-
)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
describe "graph ends after the last activity" do
|
71
|
-
let(:end_date) { Date.new(2016, 3, 1) }
|
72
|
-
|
73
|
-
it "graphs activities by month" do
|
74
|
-
subject.must_equal(
|
75
|
-
"Jan 2016" => 1,
|
76
|
-
"Feb 2016" => 1,
|
77
|
-
"Mar 2016" => 0
|
78
|
-
)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
describe "there are no activities" do
|
83
|
-
let(:activities) { [] }
|
84
|
-
|
85
|
-
it "graphs activities by month" do
|
86
|
-
subject.must_equal(
|
87
|
-
"Jan 2016" => 0,
|
88
|
-
"Feb 2016" => 0
|
89
|
-
)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
data/test/introvert_spec.rb
DELETED
@@ -1,969 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "./test/helper"
|
4
|
-
|
5
|
-
describe Friends::Introvert do
|
6
|
-
# Add readers to make internal state easier to test.
|
7
|
-
module Friends
|
8
|
-
class Introvert
|
9
|
-
attr_reader :filename, :activities, :friends
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
# Add helpers to set internal states for friends/locations/activities.
|
14
|
-
def stub_friends(val)
|
15
|
-
old_val = introvert.instance_variable_get(:@friends)
|
16
|
-
introvert.instance_variable_set(:@friends, val)
|
17
|
-
introvert.send(:set_n_activities!, :friend)
|
18
|
-
yield
|
19
|
-
introvert.instance_variable_set(:@friends, old_val)
|
20
|
-
end
|
21
|
-
|
22
|
-
def stub_activities(val)
|
23
|
-
old_val = introvert.instance_variable_get(:@activities)
|
24
|
-
introvert.instance_variable_set(:@activities, val)
|
25
|
-
introvert.send(:set_n_activities!, :friend)
|
26
|
-
introvert.send(:set_n_activities!, :location)
|
27
|
-
yield
|
28
|
-
introvert.instance_variable_set(:@activities, old_val)
|
29
|
-
end
|
30
|
-
|
31
|
-
def stub_locations(val)
|
32
|
-
old_val = introvert.instance_variable_get(:@locations)
|
33
|
-
introvert.instance_variable_set(:@locations, val)
|
34
|
-
introvert.send(:set_n_activities!, :location)
|
35
|
-
yield
|
36
|
-
introvert.instance_variable_set(:@locations, old_val)
|
37
|
-
end
|
38
|
-
|
39
|
-
let(:filename) { "test/tmp/friends.md" }
|
40
|
-
let(:args) { { filename: filename } }
|
41
|
-
let(:introvert) { Friends::Introvert.new(args) }
|
42
|
-
let(:friend_names) { ["George Washington Carver", "Betsy Ross"] }
|
43
|
-
let(:friends) do
|
44
|
-
friend_names.map do |name|
|
45
|
-
Friends::Friend.new(name: name, tags_str: "@test")
|
46
|
-
end
|
47
|
-
end
|
48
|
-
let(:activities) do
|
49
|
-
[
|
50
|
-
Friends::Activity.new(
|
51
|
-
str: "Lunch w/ **#{friend_names.first}** and **#{friend_names.last}**."
|
52
|
-
),
|
53
|
-
Friends::Activity.new(
|
54
|
-
str: "Yesterday: Called **#{friend_names.last}**."
|
55
|
-
)
|
56
|
-
]
|
57
|
-
end
|
58
|
-
let(:locations) do
|
59
|
-
[
|
60
|
-
Friends::Location.new(name: "The Eiffel Tower"),
|
61
|
-
Friends::Location.new(name: "Atlantis")
|
62
|
-
]
|
63
|
-
end
|
64
|
-
|
65
|
-
describe "#new" do
|
66
|
-
it "accepts all arguments" do
|
67
|
-
introvert # Build a new introvert.
|
68
|
-
|
69
|
-
# Check passed values.
|
70
|
-
introvert.filename.must_equal filename
|
71
|
-
end
|
72
|
-
|
73
|
-
it "has sane defaults" do
|
74
|
-
args.clear # Pass no arguments to the initializer.
|
75
|
-
introvert # Build a new introvert.
|
76
|
-
|
77
|
-
# Check default values.
|
78
|
-
introvert.filename.must_equal Friends::Introvert::DEFAULT_FILENAME
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
describe "#clean" do
|
83
|
-
subject { introvert.clean }
|
84
|
-
|
85
|
-
# Delete the file that is created each time.
|
86
|
-
after { File.delete(filename) if File.exist?(filename) }
|
87
|
-
|
88
|
-
it "writes cleaned file" do
|
89
|
-
sorted_friends = friends.sort
|
90
|
-
unsorted_friends = sorted_friends.reverse
|
91
|
-
sorted_activities = activities.sort
|
92
|
-
unsorted_activities = sorted_activities.reverse
|
93
|
-
sorted_locations = locations.sort
|
94
|
-
unsorted_locations = sorted_locations.reverse
|
95
|
-
|
96
|
-
serialized_friends = sorted_friends.map(&:serialize).join("\n")
|
97
|
-
serialized_activities = sorted_activities.map(&:serialize).join("\n")
|
98
|
-
serialized_locations = sorted_locations.map(&:serialize).join("\n")
|
99
|
-
|
100
|
-
expected_output =
|
101
|
-
"#{Friends::Introvert::ACTIVITIES_HEADER}\n"\
|
102
|
-
"#{serialized_activities}\n\n"\
|
103
|
-
"#{Friends::Introvert::FRIENDS_HEADER}\n"\
|
104
|
-
"#{serialized_friends}\n\n"\
|
105
|
-
"#{Friends::Introvert::LOCATIONS_HEADER}\n"\
|
106
|
-
"#{serialized_locations}\n"
|
107
|
-
|
108
|
-
# Read the input as unsorted, and make sure we get sorted output.
|
109
|
-
stub_friends(unsorted_friends) do
|
110
|
-
stub_activities(unsorted_activities) do
|
111
|
-
stub_locations(unsorted_locations) do
|
112
|
-
subject
|
113
|
-
File.read(filename).must_equal expected_output
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
it { subject.must_equal filename }
|
120
|
-
end
|
121
|
-
|
122
|
-
describe "#list_friends" do
|
123
|
-
subject do
|
124
|
-
introvert.list_friends(
|
125
|
-
location_name: location_name,
|
126
|
-
tagged: tagged,
|
127
|
-
verbose: verbose
|
128
|
-
)
|
129
|
-
end
|
130
|
-
|
131
|
-
describe "when a location name has been passed" do
|
132
|
-
let(:location_name) { "Atlantis" }
|
133
|
-
let(:tagged) { nil }
|
134
|
-
let(:verbose) { false }
|
135
|
-
let(:friends) do
|
136
|
-
[
|
137
|
-
Friends::Friend.new(name: "Mark Watney", location_name: "Mars"),
|
138
|
-
Friends::Friend.new(name: "Aquaman", location_name: "Atlantis"),
|
139
|
-
Friends::Friend.new(name: "Shark-Boy", location_name: "Atlantis"),
|
140
|
-
Friends::Friend.new(name: "Ms. Nowhere")
|
141
|
-
]
|
142
|
-
end
|
143
|
-
|
144
|
-
it "lists the names of friends in that location" do
|
145
|
-
stub_friends(friends) do
|
146
|
-
stub_locations(locations) do
|
147
|
-
subject.must_equal ["Aquaman", "Shark-Boy"]
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
describe "when a tag has been passed" do
|
154
|
-
let(:location_name) { nil }
|
155
|
-
let(:tagged) { "@superhero" }
|
156
|
-
let(:verbose) { false }
|
157
|
-
let(:friends) do
|
158
|
-
[
|
159
|
-
Friends::Friend.new(name: "Mark Watney"),
|
160
|
-
Friends::Friend.new(name: "Aquaman", tags_str: "@superhero"),
|
161
|
-
Friends::Friend.new(name: "Shark-Boy", tags_str: "@superhero"),
|
162
|
-
Friends::Friend.new(name: "Ms. Nowhere")
|
163
|
-
]
|
164
|
-
end
|
165
|
-
|
166
|
-
it "lists the names of friends in that location" do
|
167
|
-
stub_friends(friends) do
|
168
|
-
stub_locations(locations) do
|
169
|
-
subject.must_equal ["Aquaman", "Shark-Boy"]
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
describe "when not verbose" do
|
176
|
-
let(:verbose) { false }
|
177
|
-
let(:location_name) { nil }
|
178
|
-
let(:tagged) { nil }
|
179
|
-
it "lists the names of friends" do
|
180
|
-
stub_friends(friends) do
|
181
|
-
subject.must_equal friend_names
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
describe "when verbose" do
|
187
|
-
let(:verbose) { true }
|
188
|
-
let(:location_name) { nil }
|
189
|
-
let(:tagged) { nil }
|
190
|
-
it "lists the names and details of friends" do
|
191
|
-
stub_friends(friends) do
|
192
|
-
# Just check that there's a difference between the verbose and
|
193
|
-
# non-verbose versions of friends (otherwise our test is useless).
|
194
|
-
subject.wont_equal friend_names
|
195
|
-
|
196
|
-
subject.must_equal friends.map(&:to_s)
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
describe "#add_friend" do
|
203
|
-
let(:new_friend_name) { "Jacob Evelyn" }
|
204
|
-
subject { introvert.add_friend(name: new_friend_name) }
|
205
|
-
|
206
|
-
describe "when there is no existing friend with that name" do
|
207
|
-
it "adds the given friend" do
|
208
|
-
stub_friends(friends) do
|
209
|
-
subject
|
210
|
-
introvert.
|
211
|
-
instance_variable_get(:@friends).
|
212
|
-
map(&:name).
|
213
|
-
must_include new_friend_name
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
it "returns the friend added" do
|
218
|
-
stub_friends(friends) do
|
219
|
-
subject.name.must_equal new_friend_name
|
220
|
-
end
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
describe "when there is an existing friend with that name" do
|
225
|
-
let(:new_friend_name) { friend_names.first }
|
226
|
-
|
227
|
-
it "raises an error" do
|
228
|
-
stub_friends(friends) do
|
229
|
-
proc { subject }.must_raise Friends::FriendsError
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
describe "#add_location" do
|
236
|
-
let(:new_location_name) { "Peru" }
|
237
|
-
subject { introvert.add_location(name: new_location_name) }
|
238
|
-
|
239
|
-
describe "when there is no existing location with that name" do
|
240
|
-
it "adds the given location" do
|
241
|
-
stub_locations(locations) do
|
242
|
-
subject
|
243
|
-
introvert.list_locations.must_include new_location_name
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
it "returns the location added" do
|
248
|
-
stub_locations(locations) do
|
249
|
-
subject.name.must_equal new_location_name
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
describe "when there is an existing location with that name" do
|
255
|
-
let(:new_location_name) { locations.first.name }
|
256
|
-
|
257
|
-
it "raises an error" do
|
258
|
-
stub_locations(locations) do
|
259
|
-
proc { subject }.must_raise Friends::FriendsError
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
describe "#list_locations" do
|
266
|
-
subject { introvert.list_locations }
|
267
|
-
|
268
|
-
it "lists all locations" do
|
269
|
-
stub_locations(locations) do
|
270
|
-
subject.must_equal locations.map(&:name)
|
271
|
-
end
|
272
|
-
end
|
273
|
-
end
|
274
|
-
|
275
|
-
describe "#list_tags" do
|
276
|
-
subject { introvert.list_tags(from: from) }
|
277
|
-
|
278
|
-
let(:activities) do
|
279
|
-
[
|
280
|
-
Friends::Activity.new(str: "Lunch in the park. @picnic @food"),
|
281
|
-
Friends::Activity.new(str: "Fancy dinner. @food @swanky")
|
282
|
-
]
|
283
|
-
end
|
284
|
-
|
285
|
-
let(:friends) do
|
286
|
-
[
|
287
|
-
Friends::Friend.new(name: "Grace Hopper", tags_str: "@coder @navy"),
|
288
|
-
Friends::Friend.new(name: "James Bond", tags_str: "@cool @swanky")
|
289
|
-
]
|
290
|
-
end
|
291
|
-
|
292
|
-
describe "when from flag is nil" do
|
293
|
-
let(:from) { nil }
|
294
|
-
it "lists all tags in sorted order" do
|
295
|
-
stub_activities(activities) do
|
296
|
-
stub_friends(friends) do
|
297
|
-
subject.must_equal [
|
298
|
-
"@coder",
|
299
|
-
"@cool",
|
300
|
-
"@food",
|
301
|
-
"@navy",
|
302
|
-
"@picnic",
|
303
|
-
"@swanky"
|
304
|
-
]
|
305
|
-
end
|
306
|
-
end
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
describe 'when from flag is "activities"' do
|
311
|
-
let(:from) { "activities" }
|
312
|
-
it "lists all activity tags in sorted order" do
|
313
|
-
stub_activities(activities) do
|
314
|
-
stub_friends(friends) do
|
315
|
-
subject.must_equal ["@food", "@picnic", "@swanky"]
|
316
|
-
end
|
317
|
-
end
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
|
-
describe 'when from flag is "friends"' do
|
322
|
-
let(:from) { "friends" }
|
323
|
-
it "lists all friend tags in sorted order" do
|
324
|
-
stub_activities(activities) do
|
325
|
-
stub_friends(friends) do
|
326
|
-
subject.must_equal ["@coder", "@cool", "@navy", "@swanky"]
|
327
|
-
end
|
328
|
-
end
|
329
|
-
end
|
330
|
-
end
|
331
|
-
end
|
332
|
-
|
333
|
-
describe "#list_activities" do
|
334
|
-
subject do
|
335
|
-
introvert.list_activities(
|
336
|
-
limit: limit,
|
337
|
-
with: with,
|
338
|
-
location_name: location_name,
|
339
|
-
tagged: tagged
|
340
|
-
)
|
341
|
-
end
|
342
|
-
let(:limit) { nil }
|
343
|
-
let(:with) { nil }
|
344
|
-
let(:location_name) { nil }
|
345
|
-
let(:tagged) { nil }
|
346
|
-
|
347
|
-
describe "when the limit is lower than the number of activities" do
|
348
|
-
let(:limit) { 1 }
|
349
|
-
|
350
|
-
it "lists that number of activities" do
|
351
|
-
stub_activities(activities) do
|
352
|
-
subject.size.must_equal limit
|
353
|
-
end
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
describe "when the limit is equal to the number of activities" do
|
358
|
-
let(:limit) { activities.size }
|
359
|
-
|
360
|
-
it "lists all activities" do
|
361
|
-
stub_activities(activities) do
|
362
|
-
subject.size.must_equal activities.size
|
363
|
-
end
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
describe "when the limit is greater than the number of activities" do
|
368
|
-
let(:limit) { activities.size + 5 }
|
369
|
-
|
370
|
-
it "lists all activities" do
|
371
|
-
stub_activities(activities) do
|
372
|
-
subject.size.must_equal activities.size
|
373
|
-
end
|
374
|
-
end
|
375
|
-
end
|
376
|
-
|
377
|
-
describe "when the limit is nil" do
|
378
|
-
let(:limit) { nil }
|
379
|
-
|
380
|
-
it "lists all activities" do
|
381
|
-
stub_activities(activities) do
|
382
|
-
subject.size.must_equal activities.size
|
383
|
-
end
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
describe "when not filtering by a friend" do
|
388
|
-
let(:with) { nil }
|
389
|
-
|
390
|
-
it "lists the activities" do
|
391
|
-
stub_activities(activities) do
|
392
|
-
subject.must_equal activities.map(&:to_s)
|
393
|
-
end
|
394
|
-
end
|
395
|
-
end
|
396
|
-
|
397
|
-
describe "when filtering by part of a friend's name" do
|
398
|
-
let(:with) { "george" }
|
399
|
-
|
400
|
-
describe "when there is more than one friend match" do
|
401
|
-
let(:friend_names) { ["George Washington Carver", "George Harrison"] }
|
402
|
-
|
403
|
-
it "raises an error" do
|
404
|
-
stub_friends(friends) do
|
405
|
-
stub_activities(activities) do
|
406
|
-
proc { subject }.must_raise Friends::FriendsError
|
407
|
-
end
|
408
|
-
end
|
409
|
-
end
|
410
|
-
end
|
411
|
-
|
412
|
-
describe "when there are no friend matches" do
|
413
|
-
let(:friend_names) { ["Joe"] }
|
414
|
-
|
415
|
-
it "raises an error" do
|
416
|
-
stub_friends(friends) do
|
417
|
-
stub_activities(activities) do
|
418
|
-
proc { subject }.must_raise Friends::FriendsError
|
419
|
-
end
|
420
|
-
end
|
421
|
-
end
|
422
|
-
end
|
423
|
-
|
424
|
-
describe "when there is exactly one friend match" do
|
425
|
-
it "filters the activities by that friend" do
|
426
|
-
stub_friends(friends) do
|
427
|
-
stub_activities(activities) do
|
428
|
-
# Only one activity has that friend.
|
429
|
-
subject.must_equal activities[0..0].map(&:to_s)
|
430
|
-
end
|
431
|
-
end
|
432
|
-
end
|
433
|
-
end
|
434
|
-
end
|
435
|
-
|
436
|
-
describe "when not filtering by a location" do
|
437
|
-
let(:location_name) { nil }
|
438
|
-
|
439
|
-
it "lists the activities" do
|
440
|
-
stub_activities(activities) do
|
441
|
-
subject.must_equal activities.map(&:to_s)
|
442
|
-
end
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
describe "when filtering by part of a location name" do
|
447
|
-
let(:location_name) { "City" }
|
448
|
-
|
449
|
-
describe "when there is more than one location match" do
|
450
|
-
let(:locations) do
|
451
|
-
[
|
452
|
-
Friends::Location.new(name: "New York City"),
|
453
|
-
Friends::Location.new(name: "Kansas City")
|
454
|
-
]
|
455
|
-
end
|
456
|
-
|
457
|
-
it "raises an error" do
|
458
|
-
stub_friends(friends) do
|
459
|
-
stub_locations(locations) do
|
460
|
-
stub_activities(activities) do
|
461
|
-
proc { subject }.must_raise Friends::FriendsError
|
462
|
-
end
|
463
|
-
end
|
464
|
-
end
|
465
|
-
end
|
466
|
-
end
|
467
|
-
|
468
|
-
describe "when there are no location matches" do
|
469
|
-
let(:locations) { [Friends::Location.new(name: "Atantis")] }
|
470
|
-
|
471
|
-
it "raises an error" do
|
472
|
-
stub_friends(friends) do
|
473
|
-
stub_locations(locations) do
|
474
|
-
stub_activities(activities) do
|
475
|
-
proc { subject }.must_raise Friends::FriendsError
|
476
|
-
end
|
477
|
-
end
|
478
|
-
end
|
479
|
-
end
|
480
|
-
end
|
481
|
-
|
482
|
-
describe "when there is exactly one location match" do
|
483
|
-
let(:location_name) { "Atlantis" }
|
484
|
-
let(:activities) do
|
485
|
-
[
|
486
|
-
Friends::Activity.new(str: "Swimming near _Atlantis_."),
|
487
|
-
Friends::Activity.new(str: "Swimming somewhere else.")
|
488
|
-
]
|
489
|
-
end
|
490
|
-
|
491
|
-
it "filters the activities by that location" do
|
492
|
-
stub_friends(friends) do
|
493
|
-
stub_locations(locations) do
|
494
|
-
stub_activities(activities) do
|
495
|
-
# Only one activity has that friend.
|
496
|
-
subject.must_equal activities[0..0].map(&:to_s)
|
497
|
-
end
|
498
|
-
end
|
499
|
-
end
|
500
|
-
end
|
501
|
-
end
|
502
|
-
end
|
503
|
-
|
504
|
-
describe "when not filtering by a tag" do
|
505
|
-
let(:tagged) { nil }
|
506
|
-
|
507
|
-
it "lists the activities" do
|
508
|
-
stub_activities(activities) do
|
509
|
-
subject.must_equal activities.map(&:to_s)
|
510
|
-
end
|
511
|
-
end
|
512
|
-
end
|
513
|
-
|
514
|
-
describe "when filtering by a tag" do
|
515
|
-
let(:activities) do
|
516
|
-
[
|
517
|
-
Friends::Activity.new(str: "Tennis after work. @exercise @tennis"),
|
518
|
-
Friends::Activity.new(str: "Wimbledon! @tennis"),
|
519
|
-
Friends::Activity.new(str: "Drinks after work. @beer")
|
520
|
-
]
|
521
|
-
end
|
522
|
-
|
523
|
-
describe "when the tag ('@tag') is not used at all" do
|
524
|
-
let(:tagged) { "@garbage" }
|
525
|
-
it "returns no results" do
|
526
|
-
stub_activities(activities) do
|
527
|
-
subject.must_equal []
|
528
|
-
end
|
529
|
-
end
|
530
|
-
end
|
531
|
-
|
532
|
-
describe "when the tag ('@tag') is used once" do
|
533
|
-
let(:tagged) { "@beer" }
|
534
|
-
it "returns the activity with that tag" do
|
535
|
-
stub_activities(activities) do
|
536
|
-
subject.must_equal [activities.last.to_s]
|
537
|
-
end
|
538
|
-
end
|
539
|
-
end
|
540
|
-
|
541
|
-
describe "when the tag ('@tag') is used multiple times" do
|
542
|
-
let(:tagged) { "@tennis" }
|
543
|
-
it "returns the activities with that tag" do
|
544
|
-
stub_activities(activities) do
|
545
|
-
subject.must_equal activities[0..1].map(&:to_s)
|
546
|
-
end
|
547
|
-
end
|
548
|
-
end
|
549
|
-
end
|
550
|
-
end
|
551
|
-
|
552
|
-
describe "#add_activity" do
|
553
|
-
let(:activity_serialization) { "2014-01-01: Snorkeling with Betsy." }
|
554
|
-
let(:activity_description) { "Snorkeling with **Betsy Ross**." }
|
555
|
-
subject { introvert.add_activity(serialization: activity_serialization) }
|
556
|
-
|
557
|
-
it "adds the given activity" do
|
558
|
-
stub_friends(friends) do
|
559
|
-
subject
|
560
|
-
introvert.activities.first.description.must_equal activity_description
|
561
|
-
end
|
562
|
-
end
|
563
|
-
|
564
|
-
it "adds the activity after others on the same day" do
|
565
|
-
stub_friends(friends) do
|
566
|
-
introvert.add_activity(serialization: "2014-01-01: Ate breakfast.")
|
567
|
-
subject
|
568
|
-
introvert.activities.first.description.must_equal activity_description
|
569
|
-
end
|
570
|
-
end
|
571
|
-
|
572
|
-
it "returns the activity added" do
|
573
|
-
stub_friends(friends) do
|
574
|
-
subject.description.must_equal activity_description
|
575
|
-
end
|
576
|
-
end
|
577
|
-
end
|
578
|
-
|
579
|
-
describe "#rename_friend" do
|
580
|
-
let(:new_name) { "David Bowie" }
|
581
|
-
subject do
|
582
|
-
introvert.rename_friend(old_name: friend_names.last, new_name: new_name)
|
583
|
-
end
|
584
|
-
|
585
|
-
it "replaces old name within activities to the new name" do
|
586
|
-
stub_friends(friends) do
|
587
|
-
stub_activities(activities) do
|
588
|
-
subject
|
589
|
-
introvert.activities.first.description.must_include new_name
|
590
|
-
introvert.activities.last.description.must_include new_name
|
591
|
-
end
|
592
|
-
end
|
593
|
-
end
|
594
|
-
end
|
595
|
-
|
596
|
-
describe "#rename_location" do
|
597
|
-
subject do
|
598
|
-
introvert.rename_location(old_name: old_name, new_name: new_name)
|
599
|
-
end
|
600
|
-
let(:old_name) { "Paris" }
|
601
|
-
let(:new_name) { "Paris, France" }
|
602
|
-
|
603
|
-
let(:activities) do
|
604
|
-
[
|
605
|
-
Friends::Activity.new(str: "Dining in _Paris_."),
|
606
|
-
Friends::Activity.new(str: "Falling in love in _Paris_."),
|
607
|
-
Friends::Activity.new(str: "Swimming near _Atlantis_.")
|
608
|
-
]
|
609
|
-
end
|
610
|
-
let(:locations) do
|
611
|
-
[
|
612
|
-
Friends::Location.new(name: "Paris"),
|
613
|
-
Friends::Location.new(name: "Atlantis")
|
614
|
-
]
|
615
|
-
end
|
616
|
-
|
617
|
-
it "replaces old name within activities to the new name" do
|
618
|
-
stub_locations(locations) do
|
619
|
-
stub_activities(activities) do
|
620
|
-
subject
|
621
|
-
introvert.activities.map do |activity|
|
622
|
-
activity.description.include? new_name
|
623
|
-
end.must_equal [true, true, false]
|
624
|
-
end
|
625
|
-
end
|
626
|
-
end
|
627
|
-
|
628
|
-
describe "when there are friends at the location" do
|
629
|
-
let(:friends) do
|
630
|
-
[
|
631
|
-
Friends::Friend.new(name: "Jacques Cousteau", location_name: "Paris"),
|
632
|
-
Friends::Friend.new(name: "Marie Antoinette", location_name: "Paris"),
|
633
|
-
Friends::Friend.new(name: "Julius Caesar", location_name: "Rome")
|
634
|
-
]
|
635
|
-
end
|
636
|
-
|
637
|
-
it "updates their locations" do
|
638
|
-
stub_locations(locations) do
|
639
|
-
stub_friends(friends) do
|
640
|
-
subject
|
641
|
-
introvert.friends.map do |friend|
|
642
|
-
friend.location_name == new_name
|
643
|
-
end.must_equal [true, true, false]
|
644
|
-
end
|
645
|
-
end
|
646
|
-
end
|
647
|
-
end
|
648
|
-
end
|
649
|
-
|
650
|
-
describe "#set_location" do
|
651
|
-
subject do
|
652
|
-
introvert.set_location(
|
653
|
-
name: friend_names.first,
|
654
|
-
location_name: locations.first.name
|
655
|
-
)
|
656
|
-
end
|
657
|
-
|
658
|
-
it "returns the modified friend" do
|
659
|
-
stub_friends(friends) do
|
660
|
-
stub_locations(locations) do
|
661
|
-
subject.must_equal friends.first
|
662
|
-
end
|
663
|
-
end
|
664
|
-
end
|
665
|
-
end
|
666
|
-
|
667
|
-
describe "#add_nickname" do
|
668
|
-
subject do
|
669
|
-
introvert.add_nickname(name: friend_names.first, nickname: "The Dude")
|
670
|
-
end
|
671
|
-
|
672
|
-
it "returns the modified friend" do
|
673
|
-
stub_friends(friends) do
|
674
|
-
subject.must_equal friends.first
|
675
|
-
end
|
676
|
-
end
|
677
|
-
end
|
678
|
-
|
679
|
-
describe "#remove_nickname" do
|
680
|
-
subject do
|
681
|
-
introvert.remove_nickname(name: "Jeff", nickname: "The Dude")
|
682
|
-
end
|
683
|
-
|
684
|
-
it "returns the modified friend" do
|
685
|
-
friend = Friends::Friend.new(name: "Jeff", nickname_str: "The Dude")
|
686
|
-
stub_friends([friend]) do
|
687
|
-
subject.must_equal friend
|
688
|
-
end
|
689
|
-
end
|
690
|
-
end
|
691
|
-
|
692
|
-
describe "#add_tag" do
|
693
|
-
subject do
|
694
|
-
introvert.add_tag(name: friend_names.first, tag: "@school")
|
695
|
-
end
|
696
|
-
|
697
|
-
it "returns the modified friend" do
|
698
|
-
stub_friends(friends) do
|
699
|
-
subject.must_equal friends.first
|
700
|
-
end
|
701
|
-
end
|
702
|
-
|
703
|
-
describe "when more than one friend name matches" do
|
704
|
-
let(:friend_names) { ["George Washington Carver", "George Washington"] }
|
705
|
-
|
706
|
-
describe "when one friend name matches exactly" do
|
707
|
-
it "returns the modified friend" do
|
708
|
-
stub_friends(friends) do
|
709
|
-
subject.must_equal friends.first
|
710
|
-
end
|
711
|
-
end
|
712
|
-
end
|
713
|
-
|
714
|
-
describe "when no friend name matches exactly" do
|
715
|
-
it "raises an error" do
|
716
|
-
proc do
|
717
|
-
stub_friends(friends) do
|
718
|
-
introvert.add_tag(name: "George", tag: "@school")
|
719
|
-
end
|
720
|
-
end.must_raise Friends::FriendsError
|
721
|
-
end
|
722
|
-
end
|
723
|
-
end
|
724
|
-
end
|
725
|
-
|
726
|
-
describe "#remove_tag" do
|
727
|
-
subject do
|
728
|
-
introvert.remove_tag(name: "Jeff", tag: "@school")
|
729
|
-
end
|
730
|
-
|
731
|
-
it "returns the modified friend" do
|
732
|
-
friend = Friends::Friend.new(name: "Jeff", tags_str: "@school")
|
733
|
-
stub_friends([friend]) do
|
734
|
-
subject.must_equal friend
|
735
|
-
end
|
736
|
-
end
|
737
|
-
end
|
738
|
-
|
739
|
-
describe "#list_favorite_friends" do
|
740
|
-
subject { introvert.list_favorite_friends(limit: limit) }
|
741
|
-
|
742
|
-
describe "when there are more friends than favorites requested" do
|
743
|
-
let(:limit) { 1 }
|
744
|
-
|
745
|
-
it "returns the number of favorites requested" do
|
746
|
-
stub_friends(friends) do
|
747
|
-
stub_activities(activities) do
|
748
|
-
subject.must_equal ["Betsy Ross (2 activities)"]
|
749
|
-
end
|
750
|
-
end
|
751
|
-
end
|
752
|
-
end
|
753
|
-
end
|
754
|
-
|
755
|
-
describe "#list_favorite_locations" do
|
756
|
-
subject { introvert.list_favorite_locations(limit: limit) }
|
757
|
-
|
758
|
-
describe "when there are more locations than favorites requested" do
|
759
|
-
let(:limit) { 1 }
|
760
|
-
|
761
|
-
it "returns the number of favorites requested" do
|
762
|
-
stub_locations(locations) do
|
763
|
-
stub_activities(
|
764
|
-
[Friends::Activity.new(str: "Swimming in _Atlantis_.")]
|
765
|
-
) do
|
766
|
-
subject.must_equal ["Atlantis (1 activity)"]
|
767
|
-
end
|
768
|
-
end
|
769
|
-
end
|
770
|
-
end
|
771
|
-
end
|
772
|
-
|
773
|
-
describe "#suggest" do
|
774
|
-
subject { introvert.suggest(location_name: location_name) }
|
775
|
-
|
776
|
-
describe "when no location name is passed" do
|
777
|
-
let(:location_name) { nil }
|
778
|
-
|
779
|
-
it "returns distant, moderate, and close friends" do
|
780
|
-
stub_friends(friends) do
|
781
|
-
stub_activities(activities) do
|
782
|
-
subject.must_equal(
|
783
|
-
distant: ["George Washington Carver"],
|
784
|
-
moderate: [],
|
785
|
-
close: ["Betsy Ross"]
|
786
|
-
)
|
787
|
-
end
|
788
|
-
end
|
789
|
-
end
|
790
|
-
|
791
|
-
it "doesn't choke when there are no friends" do
|
792
|
-
stub_friends([]) do
|
793
|
-
stub_activities([]) do
|
794
|
-
subject.must_equal(
|
795
|
-
distant: [],
|
796
|
-
moderate: [],
|
797
|
-
close: []
|
798
|
-
)
|
799
|
-
end
|
800
|
-
end
|
801
|
-
end
|
802
|
-
end
|
803
|
-
|
804
|
-
describe "when a location name is passed" do
|
805
|
-
let(:location_name) { "USA" }
|
806
|
-
|
807
|
-
it "returns distant, moderate, and close friends" do
|
808
|
-
friends.first.location_name = location_name
|
809
|
-
stub_friends(friends) do
|
810
|
-
stub_activities(activities) do
|
811
|
-
subject.must_equal(
|
812
|
-
distant: ["George Washington Carver"],
|
813
|
-
moderate: [],
|
814
|
-
close: []
|
815
|
-
)
|
816
|
-
end
|
817
|
-
end
|
818
|
-
end
|
819
|
-
|
820
|
-
it "doesn't choke when there are no friends" do
|
821
|
-
stub_friends([]) do
|
822
|
-
stub_activities([]) do
|
823
|
-
subject.must_equal(
|
824
|
-
distant: [],
|
825
|
-
moderate: [],
|
826
|
-
close: []
|
827
|
-
)
|
828
|
-
end
|
829
|
-
end
|
830
|
-
end
|
831
|
-
end
|
832
|
-
end
|
833
|
-
|
834
|
-
describe "#graph" do
|
835
|
-
subject do
|
836
|
-
introvert.graph(
|
837
|
-
with: with,
|
838
|
-
location_name: location_name,
|
839
|
-
tagged: tagged
|
840
|
-
)
|
841
|
-
end
|
842
|
-
|
843
|
-
let(:with) { nil }
|
844
|
-
let(:location_name) { nil }
|
845
|
-
let(:tagged) { nil }
|
846
|
-
|
847
|
-
let(:activities) do
|
848
|
-
[
|
849
|
-
# In a location
|
850
|
-
Friends::Activity.new(
|
851
|
-
str: "2016-01-01: \
|
852
|
-
At _The Eiffel Tower_ with **George Washington Carver**."
|
853
|
-
),
|
854
|
-
|
855
|
-
# Tagged
|
856
|
-
Friends::Activity.new(
|
857
|
-
str: "2016-01-01: Called **George Washington Carver**. @phone"
|
858
|
-
),
|
859
|
-
|
860
|
-
# With a friend
|
861
|
-
Friends::Activity.new(
|
862
|
-
str: "2016-01-01: Hung out with **Betsy Ross**."
|
863
|
-
)
|
864
|
-
]
|
865
|
-
end
|
866
|
-
|
867
|
-
it "graphs activities by month" do
|
868
|
-
stub_activities(activities) do
|
869
|
-
subject.must_equal("Jan 2016" => 3)
|
870
|
-
end
|
871
|
-
end
|
872
|
-
|
873
|
-
describe "No activities" do
|
874
|
-
it "returns an empty graph" do
|
875
|
-
subject.must_equal({})
|
876
|
-
end
|
877
|
-
end
|
878
|
-
|
879
|
-
describe "Filtering by friend" do
|
880
|
-
let(:with) { "Betsy Ross" }
|
881
|
-
|
882
|
-
it "graphs activities with a friend" do
|
883
|
-
stub_friends(friends) do
|
884
|
-
stub_activities(activities) do
|
885
|
-
subject.must_equal("Jan 2016" => 1)
|
886
|
-
end
|
887
|
-
end
|
888
|
-
end
|
889
|
-
|
890
|
-
describe "when the friend does not exist" do
|
891
|
-
let(:with) { "Oscar the Grouch" }
|
892
|
-
|
893
|
-
it "raises an error" do
|
894
|
-
stub_activities(activities) do
|
895
|
-
proc { subject }.must_raise Friends::FriendsError
|
896
|
-
end
|
897
|
-
end
|
898
|
-
end
|
899
|
-
end
|
900
|
-
|
901
|
-
describe "Filtering by location" do
|
902
|
-
let(:location_name) { "The Eiffel Tower" }
|
903
|
-
|
904
|
-
it "graphs activities in a location" do
|
905
|
-
stub_locations(locations) do
|
906
|
-
stub_activities(activities) do
|
907
|
-
subject.must_equal("Jan 2016" => 1)
|
908
|
-
end
|
909
|
-
end
|
910
|
-
end
|
911
|
-
|
912
|
-
describe "when the location does not exist" do
|
913
|
-
let(:location_name) { "Nowhere" }
|
914
|
-
|
915
|
-
it "raises an error" do
|
916
|
-
stub_activities(activities) do
|
917
|
-
proc { subject }.must_raise Friends::FriendsError
|
918
|
-
end
|
919
|
-
end
|
920
|
-
end
|
921
|
-
end
|
922
|
-
|
923
|
-
describe "Filtering by tag" do
|
924
|
-
let(:tagged) { "@phone" }
|
925
|
-
|
926
|
-
it "graphs tagged activities" do
|
927
|
-
stub_activities(activities) do
|
928
|
-
subject.must_equal("Jan 2016" => 1)
|
929
|
-
end
|
930
|
-
end
|
931
|
-
end
|
932
|
-
end
|
933
|
-
|
934
|
-
describe "#total_friends" do
|
935
|
-
it "returns 0 when there are no friends" do
|
936
|
-
introvert.total_friends.must_equal 0
|
937
|
-
end
|
938
|
-
|
939
|
-
it "returns the total number of friends" do
|
940
|
-
stub_friends(friends) do
|
941
|
-
introvert.total_friends.must_equal friends.size
|
942
|
-
end
|
943
|
-
end
|
944
|
-
end
|
945
|
-
|
946
|
-
describe "#total_activities" do
|
947
|
-
it "returns 0 when there are no activities" do
|
948
|
-
introvert.total_activities.must_equal 0
|
949
|
-
end
|
950
|
-
|
951
|
-
it "returns the total number of activities" do
|
952
|
-
stub_activities(activities) do
|
953
|
-
introvert.total_activities.must_equal activities.size
|
954
|
-
end
|
955
|
-
end
|
956
|
-
end
|
957
|
-
|
958
|
-
describe "#elapsed_days" do
|
959
|
-
it "return 0 elapsed days when there are no activities" do
|
960
|
-
introvert.elapsed_days.must_equal 0
|
961
|
-
end
|
962
|
-
|
963
|
-
it "returns the number of days between the first and last activity" do
|
964
|
-
stub_activities(activities) do
|
965
|
-
introvert.elapsed_days.must_equal 1
|
966
|
-
end
|
967
|
-
end
|
968
|
-
end
|
969
|
-
end
|