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/activity_spec.rb
DELETED
@@ -1,597 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "./test/helper"
|
4
|
-
|
5
|
-
describe Friends::Activity do
|
6
|
-
let(:date) { Date.today - 1 }
|
7
|
-
let(:date_s) { date.to_s }
|
8
|
-
let(:friend1) { Friends::Friend.new(name: "Elizabeth Cady Stanton") }
|
9
|
-
let(:friend2) { Friends::Friend.new(name: "John Cage") }
|
10
|
-
let(:description) do
|
11
|
-
"Lunch with **#{friend1.name}** and **#{friend2.name}** on _The Moon_ "\
|
12
|
-
"after hanging out in _Atlantis_."
|
13
|
-
end
|
14
|
-
let(:partition) { Friends::Activity::DATE_PARTITION }
|
15
|
-
let(:activity) do
|
16
|
-
Friends::Activity.new(str: "#{date_s}#{partition}#{description}")
|
17
|
-
end
|
18
|
-
|
19
|
-
describe ".deserialize" do
|
20
|
-
subject { Friends::Activity.deserialize(serialized_str) }
|
21
|
-
|
22
|
-
describe "when serialized string is empty" do
|
23
|
-
let(:serialized_str) { "" }
|
24
|
-
|
25
|
-
it "defaults date to today and sets no description" do
|
26
|
-
today = Date.today - 7
|
27
|
-
|
28
|
-
# We stub out Date.today to guarantee that it is always the same even
|
29
|
-
# when the date changes in the middle of the test's execution. To ensure
|
30
|
-
# this technique actually works, we move our reference time backward by
|
31
|
-
# a week.
|
32
|
-
Date.stub(:today, today) do
|
33
|
-
new_activity = subject
|
34
|
-
new_activity.date.must_equal today
|
35
|
-
new_activity.description.must_equal ""
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
describe "when string is well-formed" do
|
41
|
-
let(:serialized_str) { "#{date_s}: #{description}" }
|
42
|
-
|
43
|
-
it "creates an activity with the correct date and description" do
|
44
|
-
new_activity = subject
|
45
|
-
new_activity.date.must_equal date
|
46
|
-
new_activity.description.must_equal description
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe "when date is written in natural language" do
|
51
|
-
let(:serialized_str) { "Yesterday: #{description}" }
|
52
|
-
|
53
|
-
it "creates an activity with the correct date and description" do
|
54
|
-
now = Time.now + 604800
|
55
|
-
|
56
|
-
# Chronic uses Time.now for parsing, so we stub this to prevent racy
|
57
|
-
# behavior when the date changes in the middle of test execution. To
|
58
|
-
# ensure this technique actually works, we move our reference time
|
59
|
-
# backward by a week.
|
60
|
-
Time.stub(:now, now) do
|
61
|
-
new_activity = subject
|
62
|
-
new_activity.date.must_equal (now.to_date - 1)
|
63
|
-
new_activity.description.must_equal description
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe "when no date is present" do
|
69
|
-
let(:serialized_str) { description }
|
70
|
-
|
71
|
-
it "defaults to today" do
|
72
|
-
today = Date.today - 7
|
73
|
-
|
74
|
-
# We stub out Date.today to guarantee that it is always the same even
|
75
|
-
# when the date changes in the middle of the test's execution. To ensure
|
76
|
-
# this technique actually works, we move our reference time backward by
|
77
|
-
# a week.
|
78
|
-
Date.stub(:today, today) { subject.date.must_equal today }
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
describe "when no description is present" do
|
83
|
-
let(:serialized_str) { date_s }
|
84
|
-
|
85
|
-
it "leaves description blank" do
|
86
|
-
new_activity = subject
|
87
|
-
new_activity.date.must_equal date
|
88
|
-
new_activity.description.must_equal ""
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
describe "#new" do
|
94
|
-
subject { activity }
|
95
|
-
|
96
|
-
it { subject.date.must_equal date }
|
97
|
-
it { subject.description.must_equal description }
|
98
|
-
end
|
99
|
-
|
100
|
-
describe "#to_s" do
|
101
|
-
subject { activity.to_s }
|
102
|
-
|
103
|
-
it do
|
104
|
-
subject.
|
105
|
-
must_equal "#{Paint[date_s, :bold]}: "\
|
106
|
-
"Lunch with #{Paint[friend1.name, :bold, :magenta]} and "\
|
107
|
-
"#{Paint[friend2.name, :bold, :magenta]} on "\
|
108
|
-
"#{Paint['The Moon', :bold, :yellow]} after hanging out in "\
|
109
|
-
"#{Paint['Atlantis', :bold, :yellow]}."
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
describe "#serialize" do
|
114
|
-
subject { activity.serialize }
|
115
|
-
|
116
|
-
it do
|
117
|
-
subject.
|
118
|
-
must_equal "#{Friends::Activity::SERIALIZATION_PREFIX}#{date_s}: "\
|
119
|
-
"#{description}"
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
describe "#highlight_description" do
|
124
|
-
# Add helpers to set internal states for friends and activities.
|
125
|
-
def stub_friends(val)
|
126
|
-
old_val = introvert.instance_variable_get(:@friends)
|
127
|
-
introvert.instance_variable_set(:@friends, val)
|
128
|
-
introvert.send(:set_n_activities!, :friend)
|
129
|
-
yield
|
130
|
-
introvert.instance_variable_set(:@friends, old_val)
|
131
|
-
end
|
132
|
-
|
133
|
-
def stub_activities(val)
|
134
|
-
old_val = introvert.instance_variable_get(:@activities)
|
135
|
-
introvert.instance_variable_set(:@activities, val)
|
136
|
-
introvert.send(:set_n_activities!, :friend)
|
137
|
-
introvert.send(:set_n_activities!, :location)
|
138
|
-
yield
|
139
|
-
introvert.instance_variable_set(:@activities, old_val)
|
140
|
-
end
|
141
|
-
|
142
|
-
def stub_locations(val)
|
143
|
-
old_val = introvert.instance_variable_get(:@locations)
|
144
|
-
introvert.instance_variable_set(:@locations, val)
|
145
|
-
introvert.send(:set_n_activities!, :location)
|
146
|
-
yield
|
147
|
-
introvert.instance_variable_set(:@locations, old_val)
|
148
|
-
end
|
149
|
-
|
150
|
-
let(:locations) do
|
151
|
-
[
|
152
|
-
Friends::Location.new(name: "Atlantis"),
|
153
|
-
Friends::Location.new(name: "The Moon")
|
154
|
-
]
|
155
|
-
end
|
156
|
-
let(:friends) { [friend1, friend2] }
|
157
|
-
let(:introvert) { Friends::Introvert.new }
|
158
|
-
subject do
|
159
|
-
stub_friends(friends) do
|
160
|
-
stub_locations(locations) do
|
161
|
-
activity.highlight_description(introvert: introvert)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
it "finds all friends and locations" do
|
167
|
-
subject
|
168
|
-
activity.description.must_equal "Lunch with **#{friend1.name}** and "\
|
169
|
-
"**#{friend2.name}** on _The Moon_ "\
|
170
|
-
"after hanging out in _Atlantis_."
|
171
|
-
end
|
172
|
-
|
173
|
-
describe "when description has first names" do
|
174
|
-
let(:description) { "Lunch with Elizabeth and John." }
|
175
|
-
it "matches friends" do
|
176
|
-
subject
|
177
|
-
activity.description.
|
178
|
-
must_equal "Lunch with **#{friend1.name}** and **#{friend2.name}**."
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
describe "when description has nicknames" do
|
183
|
-
let(:description) { "Lunch with Lizzy and Johnny." }
|
184
|
-
it "matches friends" do
|
185
|
-
friend1.add_nickname("Lizzy")
|
186
|
-
friend2.add_nickname("Johnny")
|
187
|
-
subject
|
188
|
-
activity.description.
|
189
|
-
must_equal "Lunch with **#{friend1.name}** and **#{friend2.name}**."
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
describe "when discription has nicknames which contain first names" do
|
194
|
-
let(:nickname1) { "Awesome #{friend1.name}" }
|
195
|
-
let(:nickname2) { "Long #{friend2.name} Silver" }
|
196
|
-
let(:description) { "Lunch with #{nickname1} and #{nickname2}." }
|
197
|
-
it "matches friends" do
|
198
|
-
friend1.add_nickname(nickname1)
|
199
|
-
friend2.add_nickname(nickname2)
|
200
|
-
subject
|
201
|
-
activity.description.
|
202
|
-
must_equal "Lunch with **#{friend1.name}** and **#{friend2.name}**."
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
describe 'when description ends with "<first name> <last name initial>"' do
|
207
|
-
let(:description) { "Lunch with John C" }
|
208
|
-
it "matches the friend" do
|
209
|
-
subject
|
210
|
-
activity.description.
|
211
|
-
must_equal "Lunch with **#{friend2.name}**"
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
describe 'when description ends with "<first name> <last name initial>".' do
|
216
|
-
let(:description) { "Lunch with John C." }
|
217
|
-
it "matches the friend and keeps the period" do
|
218
|
-
subject
|
219
|
-
activity.description.
|
220
|
-
must_equal "Lunch with **#{friend2.name}**."
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
describe "when description has \"<first name> <last name initial>\" in "\
|
225
|
-
"the middle of a sentence" do
|
226
|
-
let(:description) { "Lunch with John C in the park." }
|
227
|
-
it "matches the friend" do
|
228
|
-
subject
|
229
|
-
activity.description.
|
230
|
-
must_equal "Lunch with **#{friend2.name}** in the park."
|
231
|
-
end
|
232
|
-
end
|
233
|
-
|
234
|
-
describe "when description has \"<first name> <last name initial>.\" in "\
|
235
|
-
"the middle of a sentence" do
|
236
|
-
let(:description) { "Lunch with John C. in the park." }
|
237
|
-
it "matches the friend and swallows the period" do
|
238
|
-
subject
|
239
|
-
activity.description.
|
240
|
-
must_equal "Lunch with **#{friend2.name}** in the park."
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
describe "when description has \"<first name> <last name initial>\". at "\
|
245
|
-
"the end of a sentence" do
|
246
|
-
let(:description) { "Lunch with John C. It was great!" }
|
247
|
-
it "matches the friend and keeps the period" do
|
248
|
-
subject
|
249
|
-
activity.description.
|
250
|
-
must_equal "Lunch with **#{friend2.name}**. It was great!"
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
describe "when names are not entered case-sensitively" do
|
255
|
-
let(:description) { "Lunch with elizabeth cady stanton." }
|
256
|
-
it "matches friends" do
|
257
|
-
subject
|
258
|
-
activity.description.must_equal "Lunch with **Elizabeth Cady Stanton**."
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
describe "when name is at beginning of word" do
|
263
|
-
let(:description) { "Field trip to the Johnson Co." }
|
264
|
-
it "does not match a friend" do
|
265
|
-
subject
|
266
|
-
# No match found.
|
267
|
-
activity.description.must_equal "Field trip to the Johnson Co."
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
describe "when name is in middle of word" do
|
272
|
-
let(:description) { "Field trip to the JimJohnJames Co." }
|
273
|
-
it "does not match a friend" do
|
274
|
-
subject
|
275
|
-
# No match found.
|
276
|
-
activity.description.must_equal "Field trip to the JimJohnJames Co."
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
describe "when one name ends another after a hyphen" do
|
281
|
-
let(:friend1) { Friends::Friend.new(name: "Mary-Kate Olsen") }
|
282
|
-
let(:friend2) { Friends::Friend.new(name: "Kate Winslet") }
|
283
|
-
let(:description) { "Shopping with Mary-Kate." }
|
284
|
-
|
285
|
-
it "gives precedence to the larger name" do
|
286
|
-
# Make sure "Kate" is a closer friend than "Mary-Kate" so we know our
|
287
|
-
# test result isn't due to chance.
|
288
|
-
friend1.n_activities = 0
|
289
|
-
friend2.n_activities = 10
|
290
|
-
|
291
|
-
subject
|
292
|
-
activity.description.must_equal "Shopping with **Mary-Kate Olsen**."
|
293
|
-
end
|
294
|
-
end
|
295
|
-
|
296
|
-
describe "when one name preceeds another before a hyphen" do
|
297
|
-
let(:friend1) { Friends::Friend.new(name: "Mary-Kate Olsen") }
|
298
|
-
let(:friend2) { Friends::Friend.new(name: "Mary Poppins") }
|
299
|
-
let(:description) { "Shopping with Mary-Kate." }
|
300
|
-
|
301
|
-
it "gives precedence to the larger name" do
|
302
|
-
# Make sure "Kate" is a closer friend than "Mary-Kate" so we know our
|
303
|
-
# test result isn't due to chance.
|
304
|
-
friend1.n_activities = 0
|
305
|
-
friend2.n_activities = 10
|
306
|
-
|
307
|
-
subject
|
308
|
-
activity.description.must_equal "Shopping with **Mary-Kate Olsen**."
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
describe "when one name is contained within another via a hyphen" do
|
313
|
-
let(:friend1) { Friends::Friend.new(name: "Mary-Jo-Kate Olsen") }
|
314
|
-
let(:friend2) { Friends::Friend.new(name: "Jo Stafford") }
|
315
|
-
let(:description) { "Shopping with Mary-Jo-Kate." }
|
316
|
-
|
317
|
-
it "gives precedence to the larger name" do
|
318
|
-
# Make sure "Kate" is a closer friend than "Mary-Kate" so we know our
|
319
|
-
# test result isn't due to chance.
|
320
|
-
friend1.n_activities = 0
|
321
|
-
friend2.n_activities = 10
|
322
|
-
|
323
|
-
subject
|
324
|
-
activity.description.must_equal "Shopping with **Mary-Jo-Kate Olsen**."
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
|
-
describe "when name is at end of word" do
|
329
|
-
let(:description) { "Field trip to the JimJohn Co." }
|
330
|
-
it "does not match a friend" do
|
331
|
-
subject
|
332
|
-
# No match found.
|
333
|
-
activity.description.must_equal "Field trip to the JimJohn Co."
|
334
|
-
end
|
335
|
-
end
|
336
|
-
|
337
|
-
describe "when name is escaped with a backslash" do
|
338
|
-
# We have to use two backslashes here because that's how Ruby encodes one.
|
339
|
-
let(:description) { "Dinner with \\Elizabeth Cady Stanton." }
|
340
|
-
it "does not match a friend and removes the backslash" do
|
341
|
-
subject
|
342
|
-
# No match found.
|
343
|
-
activity.description.must_equal "Dinner with Elizabeth Cady Stanton."
|
344
|
-
end
|
345
|
-
end
|
346
|
-
|
347
|
-
describe "when name has leading asterisks" do
|
348
|
-
let(:description) { "Dinner with **Elizabeth Cady Stanton." }
|
349
|
-
it "does not match a friend" do
|
350
|
-
subject
|
351
|
-
# No match found.
|
352
|
-
activity.description.must_equal "Dinner with **Elizabeth Cady Stanton."
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
describe "when name has ending asterisks" do
|
357
|
-
let(:description) { "Dinner with Elizabeth**." }
|
358
|
-
it "does not match a friend" do
|
359
|
-
subject
|
360
|
-
|
361
|
-
# Note: for now we can't guarantee that "Elizabeth Cady Stanton**" won't
|
362
|
-
# match, because the Elizabeth isn't surrounded by asterisks.
|
363
|
-
activity.description.must_equal "Dinner with Elizabeth**."
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
describe "when a friend's name is mentioned multiple times" do
|
368
|
-
let(:description) { "Dinner with Elizabeth. Elizabeth made us pasta." }
|
369
|
-
it "highlights all occurrences of the friend's name" do
|
370
|
-
subject
|
371
|
-
activity.description.
|
372
|
-
must_equal "Dinner with **Elizabeth Cady Stanton**."\
|
373
|
-
" **Elizabeth Cady Stanton** made us pasta."
|
374
|
-
end
|
375
|
-
end
|
376
|
-
|
377
|
-
describe "when there are multiple matches" do
|
378
|
-
describe "when there is context from past activities" do
|
379
|
-
let(:description) { "Dinner with Elizabeth and John." }
|
380
|
-
let(:friends) do
|
381
|
-
[
|
382
|
-
friend1,
|
383
|
-
friend2,
|
384
|
-
Friends::Friend.new(name: "Elizabeth II")
|
385
|
-
]
|
386
|
-
end
|
387
|
-
|
388
|
-
it "chooses a match based on the context" do
|
389
|
-
# Create a past activity in which Elizabeth Cady Stanton did something
|
390
|
-
# with John Cage. Then, create past activities to make Elizabeth II a
|
391
|
-
# better friend than Elizabeth Cady Stanton.
|
392
|
-
old_activities = [
|
393
|
-
Friends::Activity.new(
|
394
|
-
str: "#{date_s}#{partition}Picnic with "\
|
395
|
-
"**Elizabeth Cady Stanton** and **John Cage**."
|
396
|
-
),
|
397
|
-
Friends::Activity.new(
|
398
|
-
str: "#{date_s}#{partition}Got lunch with **Elizabeth II**."
|
399
|
-
),
|
400
|
-
Friends::Activity.new(
|
401
|
-
str: "#{date_s}#{partition}Ice skated with **Elizabeth II**."
|
402
|
-
)
|
403
|
-
]
|
404
|
-
|
405
|
-
# Elizabeth II is the better friend, but historical activities have
|
406
|
-
# had Elizabeth Cady Stanton and John Cage together. Thus, we should
|
407
|
-
# interpret "Elizabeth" as Elizabeth Cady Stanton.
|
408
|
-
stub_activities(old_activities) { subject }
|
409
|
-
|
410
|
-
activity.description.
|
411
|
-
must_equal "Dinner with **Elizabeth Cady Stanton** and "\
|
412
|
-
"**John Cage**."
|
413
|
-
end
|
414
|
-
end
|
415
|
-
|
416
|
-
describe "when there is no context from past activities" do
|
417
|
-
let(:description) { "Dinner with Elizabeth." }
|
418
|
-
|
419
|
-
it "falls back to choosing the better friend" do
|
420
|
-
friend2.name = "Elizabeth II"
|
421
|
-
|
422
|
-
# Give a past activity to Elizabeth II.
|
423
|
-
old_activity = Friends::Activity.new(
|
424
|
-
str: "#{date_s}#{partition}Do something with **Elizabeth II**."
|
425
|
-
)
|
426
|
-
|
427
|
-
stub_activities([old_activity]) { subject }
|
428
|
-
|
429
|
-
# Pick the friend with more activities.
|
430
|
-
activity.description.must_equal "Dinner with **Elizabeth II**."
|
431
|
-
end
|
432
|
-
end
|
433
|
-
end
|
434
|
-
end
|
435
|
-
|
436
|
-
describe "#includes_location?" do
|
437
|
-
subject { activity.includes_location?(loc) }
|
438
|
-
let(:loc) { Friends::Location.new(name: "Atlantis") }
|
439
|
-
|
440
|
-
describe "when the given location is in the activity" do
|
441
|
-
let(:activity) { Friends::Activity.new(str: "Explored _#{loc.name}_") }
|
442
|
-
it { subject.must_equal true }
|
443
|
-
end
|
444
|
-
|
445
|
-
describe "when the given location is not in the activity" do
|
446
|
-
let(:activity) { Friends::Activity.new(str: "Explored _Elsewhere_") }
|
447
|
-
it { subject.must_equal false }
|
448
|
-
end
|
449
|
-
end
|
450
|
-
|
451
|
-
describe "#includes_friend?" do
|
452
|
-
subject { activity.includes_friend?(friend) }
|
453
|
-
|
454
|
-
describe "when the given friend is in the activity" do
|
455
|
-
let(:friend) { friend1 }
|
456
|
-
it { subject.must_equal true }
|
457
|
-
end
|
458
|
-
|
459
|
-
describe "when the given friend is not in the activity" do
|
460
|
-
let(:friend) { Friends::Friend.new(name: "Claude Debussy") }
|
461
|
-
it { subject.must_equal false }
|
462
|
-
end
|
463
|
-
end
|
464
|
-
|
465
|
-
describe "#tags" do
|
466
|
-
subject { activity.tags }
|
467
|
-
|
468
|
-
describe "when the activity has no tags" do
|
469
|
-
let(:activity) { Friends::Activity.new(str: "Enormous ball pit!") }
|
470
|
-
it { subject.must_be :empty? }
|
471
|
-
end
|
472
|
-
|
473
|
-
describe "when the activity has tags" do
|
474
|
-
let(:activity) { Friends::Activity.new(str: "Party! @fun @crazy @fun") }
|
475
|
-
it { subject.must_equal Set.new(["@fun", "@crazy"]) }
|
476
|
-
end
|
477
|
-
end
|
478
|
-
|
479
|
-
describe "#includes_tag?" do
|
480
|
-
subject { activity.includes_tag?(tag) }
|
481
|
-
let(:activity) { Friends::Activity.new(str: "Enormous ball pit! @fun") }
|
482
|
-
|
483
|
-
describe "when the given tag is not in the activity" do
|
484
|
-
let(:tag) { "@garbage" }
|
485
|
-
it { subject.must_equal false }
|
486
|
-
end
|
487
|
-
|
488
|
-
describe "when the given word is in the activity but not as a tag" do
|
489
|
-
let(:tag) { "@ball" }
|
490
|
-
it { subject.must_equal false }
|
491
|
-
end
|
492
|
-
|
493
|
-
describe "when the given tag is in the activity" do
|
494
|
-
let(:tag) { "@fun" }
|
495
|
-
it { subject.must_equal true }
|
496
|
-
end
|
497
|
-
end
|
498
|
-
|
499
|
-
describe "#friend_names" do
|
500
|
-
subject { activity.friend_names }
|
501
|
-
|
502
|
-
it "returns a list of friend names" do
|
503
|
-
names = subject
|
504
|
-
|
505
|
-
# We don't assert that the output must be in a specific order because we
|
506
|
-
# don't care about the order and it is subject to change.
|
507
|
-
names.size.must_equal 2
|
508
|
-
names.must_include "Elizabeth Cady Stanton"
|
509
|
-
names.must_include "John Cage"
|
510
|
-
end
|
511
|
-
|
512
|
-
describe "when a friend is mentioned more than once" do
|
513
|
-
let(:description) { "Lunch with **John Cage**. **John Cage** can eat!" }
|
514
|
-
|
515
|
-
it "removes duplicate names" do
|
516
|
-
subject.must_equal ["John Cage"]
|
517
|
-
end
|
518
|
-
end
|
519
|
-
end
|
520
|
-
|
521
|
-
describe "#<=>" do
|
522
|
-
it "sorts by reverse-date" do
|
523
|
-
past_act = Friends::Activity.new(str: "Yesterday: Dummy")
|
524
|
-
future_act = Friends::Activity.new(str: "Tomorrow: Dummy")
|
525
|
-
[past_act, future_act].sort.must_equal [future_act, past_act]
|
526
|
-
end
|
527
|
-
end
|
528
|
-
|
529
|
-
describe "#update_friend_name" do
|
530
|
-
let(:description) { "Lunch with **John Candy**." }
|
531
|
-
subject do
|
532
|
-
activity.update_friend_name(
|
533
|
-
old_name: "John Candy",
|
534
|
-
new_name: "John Cleese"
|
535
|
-
)
|
536
|
-
end
|
537
|
-
|
538
|
-
it "renames the given friend in the description" do
|
539
|
-
subject.must_equal "Lunch with **John Cleese**."
|
540
|
-
end
|
541
|
-
|
542
|
-
describe "when the description contains a fragment of the old name" do
|
543
|
-
let(:description) { "Lunch with **John Candy** at Johnny's Diner." }
|
544
|
-
|
545
|
-
it "only replaces the name" do
|
546
|
-
subject.must_equal "Lunch with **John Cleese** at Johnny's Diner."
|
547
|
-
end
|
548
|
-
end
|
549
|
-
|
550
|
-
describe "when the description contains the complete old name" do
|
551
|
-
let(:description) { "Coffee with **John** at John's Studio." }
|
552
|
-
subject do
|
553
|
-
activity.update_friend_name(old_name: "John", new_name: "Joe")
|
554
|
-
end
|
555
|
-
|
556
|
-
it "only replaces the actual name" do
|
557
|
-
subject.must_equal "Coffee with **Joe** at John's Studio."
|
558
|
-
end
|
559
|
-
end
|
560
|
-
end
|
561
|
-
|
562
|
-
describe "#update_location_name" do
|
563
|
-
let(:description) { "Lunch in _Paris_." }
|
564
|
-
subject do
|
565
|
-
activity.update_location_name(
|
566
|
-
old_name: "Paris",
|
567
|
-
new_name: "Paris, France"
|
568
|
-
)
|
569
|
-
end
|
570
|
-
|
571
|
-
it "renames the given friend in the description" do
|
572
|
-
subject.must_equal "Lunch in _Paris, France_."
|
573
|
-
end
|
574
|
-
|
575
|
-
describe "when the description contains a fragment of the old name" do
|
576
|
-
let(:description) { "Lunch in _Paris_ at the Parisian Café." }
|
577
|
-
|
578
|
-
it "only replaces the name" do
|
579
|
-
subject.must_equal "Lunch in _Paris, France_ at the Parisian Café."
|
580
|
-
end
|
581
|
-
end
|
582
|
-
|
583
|
-
describe "when the description contains the complete old name" do
|
584
|
-
let(:description) { "Lunch in _Paris_ at The Paris Café." }
|
585
|
-
subject do
|
586
|
-
activity.update_location_name(
|
587
|
-
old_name: "Paris",
|
588
|
-
new_name: "Paris, France"
|
589
|
-
)
|
590
|
-
end
|
591
|
-
|
592
|
-
it "only replaces the actual name" do
|
593
|
-
subject.must_equal "Lunch in _Paris, France_ at The Paris Café."
|
594
|
-
end
|
595
|
-
end
|
596
|
-
end
|
597
|
-
end
|