friends 0.16 → 0.17

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.
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+ # Location represents a location in the world.
3
+
4
+ require "friends/regex_builder"
5
+ require "friends/serializable"
6
+
7
+ module Friends
8
+ class Location
9
+ extend Serializable
10
+
11
+ SERIALIZATION_PREFIX = "- ".freeze
12
+
13
+ # @return [Regexp] the regex for capturing groups in deserialization
14
+ def self.deserialization_regex
15
+ # Note: this regex must be on one line because whitespace is important
16
+ /(#{SERIALIZATION_PREFIX})?(?<name>.+)/
17
+ end
18
+
19
+ # @return [Regexp] the string of what we expected during deserialization
20
+ def self.deserialization_expectation
21
+ "[Location Name]"
22
+ end
23
+
24
+ # @param name [String] the name of the location
25
+ def initialize(name:)
26
+ @name = name
27
+ end
28
+
29
+ attr_accessor :name
30
+
31
+ # @return [String] the file serialization text for the location
32
+ def serialize
33
+ "#{SERIALIZATION_PREFIX}#{@name}"
34
+ end
35
+
36
+ # @return [Regexp] the regex used to match this location's name in an
37
+ # activity description
38
+ def regex_for_name
39
+ Friends::RegexBuilder.regex(@name)
40
+ end
41
+
42
+ private
43
+
44
+ # Default sorting for an array of locations is alphabetical.
45
+ def <=>(other)
46
+ name <=> other.name
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+ # RegexpBuilder is an internal class that helps us build regexes to find things.
3
+
4
+ module Friends
5
+ class RegexBuilder
6
+ # We don't want to match strings that are "escaped" with a leading
7
+ # backslash.
8
+ NO_LEADING_BACKSLASH = "(?<!\\\\)".freeze
9
+
10
+ # We don't want to match strings that are directly touching double asterisks
11
+ # as these are treated as sacred by our program.
12
+ NO_LEADING_ASTERISKS = "(?<!\\*\\*)".freeze
13
+ NO_TRAILING_ASTERISKS = "(?!\\*\\*)".freeze
14
+
15
+ # We don't want to match strings that are directly touching underscores
16
+ # as these are treated as sacred by our program.
17
+ NO_LEADING_UNDERSCORES = "(?<!_)".freeze
18
+ NO_TRAILING_UNDERSCORES = "(?!_)".freeze
19
+
20
+ # We don't want to match strings that are part of other words.
21
+ NO_LEADING_ALPHABETICALS = "(?<![A-z])".freeze
22
+ NO_TRAILING_ALPHABETICALS = "(?![A-z])".freeze
23
+
24
+ def self.regex(str)
25
+ Regexp.new(
26
+ NO_LEADING_BACKSLASH +
27
+ NO_LEADING_ASTERISKS +
28
+ NO_LEADING_UNDERSCORES +
29
+ NO_LEADING_ALPHABETICALS +
30
+ str +
31
+ NO_TRAILING_ALPHABETICALS +
32
+ NO_TRAILING_UNDERSCORES +
33
+ NO_TRAILING_ASTERISKS,
34
+ Regexp::IGNORECASE
35
+ )
36
+ end
37
+ end
38
+ end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Friends
3
- VERSION = "0.16".freeze
3
+ VERSION = "0.17".freeze
4
4
  end
@@ -5,7 +5,10 @@ describe Friends::Activity do
5
5
  let(:date_s) { date.to_s }
6
6
  let(:friend1) { Friends::Friend.new(name: "Elizabeth Cady Stanton") }
7
7
  let(:friend2) { Friends::Friend.new(name: "John Cage") }
8
- let(:description) { "Lunch with **#{friend1.name}** and **#{friend2.name}**" }
8
+ let(:description) do
9
+ "Lunch with **#{friend1.name}** and **#{friend2.name}** on _The Moon_ "\
10
+ "after hanging out in _Atlantis_."
11
+ end
9
12
  let(:partition) { Friends::Activity::DATE_PARTITION }
10
13
  let(:activity) do
11
14
  Friends::Activity.new(str: "#{date_s}#{partition}#{description}")
@@ -99,7 +102,9 @@ describe Friends::Activity do
99
102
  subject.
100
103
  must_equal "#{Paint[date_s, :bold]}: "\
101
104
  "Lunch with #{Paint[friend1.name, :bold, :magenta]} and "\
102
- "#{Paint[friend2.name, :bold, :magenta]}"
105
+ "#{Paint[friend2.name, :bold, :magenta]} on "\
106
+ "#{Paint['The Moon', :bold, :yellow]} after hanging out in "\
107
+ "#{Paint['Atlantis', :bold, :yellow]}."
103
108
  end
104
109
  end
105
110
 
@@ -113,7 +118,7 @@ describe Friends::Activity do
113
118
  end
114
119
  end
115
120
 
116
- describe "#highlight_friends" do
121
+ describe "#highlight_description" do
117
122
  # Add helpers to set internal states for friends and activities.
118
123
  def stub_friends(val)
119
124
  old_val = introvert.instance_variable_get(:@friends)
@@ -129,16 +134,34 @@ describe Friends::Activity do
129
134
  introvert.instance_variable_set(:@activities, old_val)
130
135
  end
131
136
 
137
+ def stub_locations(val)
138
+ old_val = introvert.instance_variable_get(:@locations)
139
+ introvert.instance_variable_set(:@locations, val)
140
+ yield
141
+ introvert.instance_variable_set(:@locations, old_val)
142
+ end
143
+
144
+ let(:locations) do
145
+ [
146
+ Friends::Location.new(name: "Atlantis"),
147
+ Friends::Location.new(name: "The Moon")
148
+ ]
149
+ end
132
150
  let(:friends) { [friend1, friend2] }
133
151
  let(:introvert) { Friends::Introvert.new }
134
152
  subject do
135
- stub_friends(friends) { activity.highlight_friends(introvert: introvert) }
153
+ stub_friends(friends) do
154
+ stub_locations(locations) do
155
+ activity.highlight_description(introvert: introvert)
156
+ end
157
+ end
136
158
  end
137
159
 
138
- it "finds all friends" do
160
+ it "finds all friends and locations" do
139
161
  subject
140
- activity.description.
141
- must_equal "Lunch with **#{friend1.name}** and **#{friend2.name}**"
162
+ activity.description.must_equal "Lunch with **#{friend1.name}** and "\
163
+ "**#{friend2.name}** on _The Moon_ "\
164
+ "after hanging out in _Atlantis_."
142
165
  end
143
166
 
144
167
  describe "when description has first names" do
@@ -332,23 +355,32 @@ describe Friends::Activity do
332
355
  end
333
356
  end
334
357
 
358
+ describe "#includes_location?" do
359
+ subject { activity.includes_location?(location: loc) }
360
+ let(:loc) { Friends::Location.new(name: "Atlantis") }
361
+
362
+ describe "when the given location is in the activity" do
363
+ let(:activity) { Friends::Activity.new(str: "Explored _#{loc.name}_") }
364
+ it { subject.must_equal true }
365
+ end
366
+
367
+ describe "when the given location is not in the activity" do
368
+ let(:activity) { Friends::Activity.new(str: "Explored _Elsewhere_") }
369
+ it { subject.must_equal false }
370
+ end
371
+ end
372
+
335
373
  describe "#includes_friend?" do
336
374
  subject { activity.includes_friend?(friend: friend) }
337
375
 
338
376
  describe "when the given friend is in the activity" do
339
377
  let(:friend) { friend1 }
340
-
341
- it "returns true" do
342
- subject.must_equal true
343
- end
378
+ it { subject.must_equal true }
344
379
  end
345
380
 
346
381
  describe "when the given friend is not in the activity" do
347
382
  let(:friend) { Friends::Friend.new(name: "Claude Debussy") }
348
-
349
- it "returns false" do
350
- subject.must_equal false
351
- end
383
+ it { subject.must_equal false }
352
384
  end
353
385
  end
354
386
 
@@ -382,10 +414,13 @@ describe Friends::Activity do
382
414
  end
383
415
  end
384
416
 
385
- describe "#update_name" do
417
+ describe "#update_friend_name" do
386
418
  let(:description) { "Lunch with **John Candy**." }
387
419
  subject do
388
- activity.update_name(old_name: "John Candy", new_name: "John Cleese")
420
+ activity.update_friend_name(
421
+ old_name: "John Candy",
422
+ new_name: "John Cleese"
423
+ )
389
424
  end
390
425
 
391
426
  it "renames the given friend in the description" do
@@ -403,7 +438,7 @@ describe Friends::Activity do
403
438
  describe "when the description contains the complete old name" do
404
439
  let(:description) { "Coffee with **John** at John's Studio." }
405
440
  subject do
406
- activity.update_name(old_name: "John", new_name: "Joe")
441
+ activity.update_friend_name(old_name: "John", new_name: "Joe")
407
442
  end
408
443
 
409
444
  it "only replaces the actual name" do
@@ -411,4 +446,40 @@ describe Friends::Activity do
411
446
  end
412
447
  end
413
448
  end
449
+
450
+ describe "#update_location_name" do
451
+ let(:description) { "Lunch in _Paris_." }
452
+ subject do
453
+ activity.update_location_name(
454
+ old_name: "Paris",
455
+ new_name: "Paris, France"
456
+ )
457
+ end
458
+
459
+ it "renames the given friend in the description" do
460
+ subject.must_equal "Lunch in _Paris, France_."
461
+ end
462
+
463
+ describe "when the description contains a fragment of the old name" do
464
+ let(:description) { "Lunch in _Paris_ at the Parisian Café." }
465
+
466
+ it "only replaces the name" do
467
+ subject.must_equal "Lunch in _Paris, France_ at the Parisian Café."
468
+ end
469
+ end
470
+
471
+ describe "when the description contains the complete old name" do
472
+ let(:description) { "Lunch in _Paris_ at The Paris Café." }
473
+ subject do
474
+ activity.update_location_name(
475
+ old_name: "Paris",
476
+ new_name: "Paris, France"
477
+ )
478
+ end
479
+
480
+ it "only replaces the actual name" do
481
+ subject.must_equal "Lunch in _Paris, France_ at The Paris Café."
482
+ end
483
+ end
484
+ end
414
485
  end
@@ -30,15 +30,6 @@ describe Friends::Friend do
30
30
  it { subject.name.must_equal friend_name }
31
31
  end
32
32
 
33
- describe "#rename" do
34
- subject { friend }
35
-
36
- it "renames the friend" do
37
- friend.rename("Ada Lovelace")
38
- subject.name.must_equal "Ada Lovelace"
39
- end
40
- end
41
-
42
33
  describe "#serialize" do
43
34
  subject { friend.serialize }
44
35
 
@@ -118,10 +109,8 @@ describe Friends::Friend do
118
109
  subject { friend.regexes_for_name }
119
110
 
120
111
  it "generates appropriate regexes" do
121
- subject.must_equal [
122
- /(?<!\\)(?<!\*\*)(?<![A-z])Jacob\s+Evelyn(?![A-z])(?!\*\*)/i,
123
- /(?<!\\)(?<!\*\*)(?<![A-z])Jacob(?![A-z])(?!\*\*)/i
124
- ]
112
+ subject.any? { |r| r =~ friend_name }.must_equal true
113
+ subject.any? { |r| r =~ friend_name.partition(" ").first }.must_equal true
125
114
  end
126
115
  end
127
116
 
@@ -8,7 +8,7 @@ describe Friends::Introvert do
8
8
  end
9
9
  end
10
10
 
11
- # Add helpers to set internal states for friends and activities.
11
+ # Add helpers to set internal states for friends/locations/activities.
12
12
  def stub_friends(val)
13
13
  old_val = introvert.instance_variable_get(:@friends)
14
14
  introvert.instance_variable_set(:@friends, val)
@@ -23,6 +23,13 @@ describe Friends::Introvert do
23
23
  introvert.instance_variable_set(:@activities, old_val)
24
24
  end
25
25
 
26
+ def stub_locations(val)
27
+ old_val = introvert.instance_variable_get(:@locations)
28
+ introvert.instance_variable_set(:@locations, val)
29
+ yield
30
+ introvert.instance_variable_set(:@locations, old_val)
31
+ end
32
+
26
33
  let(:filename) { "test/tmp/friends.md" }
27
34
  let(:args) { { filename: filename } }
28
35
  let(:introvert) { Friends::Introvert.new(args) }
@@ -38,6 +45,12 @@ describe Friends::Introvert do
38
45
  )
39
46
  ]
40
47
  end
48
+ let(:locations) do
49
+ [
50
+ Friends::Location.new(name: "The Eiffel Tower"),
51
+ Friends::Location.new(name: "Atlantis")
52
+ ]
53
+ end
41
54
 
42
55
  describe "#new" do
43
56
  it "accepts all arguments" do
@@ -67,22 +80,28 @@ describe Friends::Introvert do
67
80
  unsorted_friends = sorted_friends.reverse
68
81
  sorted_activities = activities.sort
69
82
  unsorted_activities = sorted_activities.reverse
83
+ sorted_locations = locations.sort
84
+ unsorted_locations = sorted_locations.reverse
70
85
 
71
- serialized_names = sorted_friends.map(&:serialize)
72
- name_output = serialized_names.join("\n")
73
-
74
- serialized_descriptions = sorted_activities.map(&:serialize)
75
- descriptions_output = serialized_descriptions.join("\n")
86
+ serialized_friends = sorted_friends.map(&:serialize).join("\n")
87
+ serialized_activities = sorted_activities.map(&:serialize).join("\n")
88
+ serialized_locations = sorted_locations.map(&:serialize).join("\n")
76
89
 
77
90
  expected_output =
78
- "#{Friends::Introvert::ACTIVITIES_HEADER}\n#{descriptions_output}\n\n"\
79
- "#{Friends::Introvert::FRIENDS_HEADER}\n#{name_output}\n"
91
+ "#{Friends::Introvert::ACTIVITIES_HEADER}\n"\
92
+ "#{serialized_activities}\n\n"\
93
+ "#{Friends::Introvert::FRIENDS_HEADER}\n"\
94
+ "#{serialized_friends}\n\n"\
95
+ "#{Friends::Introvert::LOCATIONS_HEADER}\n"\
96
+ "#{serialized_locations}\n"
80
97
 
81
98
  # Read the input as unsorted, and make sure we get sorted output.
82
99
  stub_friends(unsorted_friends) do
83
100
  stub_activities(unsorted_activities) do
84
- subject
85
- File.read(filename).must_equal expected_output
101
+ stub_locations(unsorted_locations) do
102
+ subject
103
+ File.read(filename).must_equal expected_output
104
+ end
86
105
  end
87
106
  end
88
107
  end
@@ -91,11 +110,35 @@ describe Friends::Introvert do
91
110
  end
92
111
 
93
112
  describe "#list_friends" do
94
- subject { introvert.list_friends }
113
+ subject { introvert.list_friends(location_name: location_name) }
95
114
 
96
- it "lists the names of friends" do
97
- stub_friends(friends) do
98
- subject.must_equal friend_names
115
+ describe "when no location name has been passed" do
116
+ let(:location_name) { nil }
117
+
118
+ it "lists the names of friends" do
119
+ stub_friends(friends) do
120
+ subject.must_equal friend_names
121
+ end
122
+ end
123
+ end
124
+
125
+ describe "when a location name has been passed" do
126
+ let(:location_name) { "Atlantis" }
127
+ let(:friends) do
128
+ [
129
+ Friends::Friend.new(name: "Mark Watney", location_name: "Mars"),
130
+ Friends::Friend.new(name: "Aquaman", location_name: "Atlantis"),
131
+ Friends::Friend.new(name: "Shark-Boy", location_name: "Atlantis"),
132
+ Friends::Friend.new(name: "Ms. Nowhere")
133
+ ]
134
+ end
135
+
136
+ it "lists the names of friends" do
137
+ stub_friends(friends) do
138
+ stub_locations(locations) do
139
+ subject.must_equal ["Aquaman", "Shark-Boy"]
140
+ end
141
+ end
99
142
  end
100
143
  end
101
144
  end
@@ -104,14 +147,12 @@ describe Friends::Introvert do
104
147
  let(:new_friend_name) { "Jacob Evelyn" }
105
148
  subject { introvert.add_friend(name: new_friend_name) }
106
149
 
107
- # Delete the file that is created each time.
108
- after { File.delete(filename) if File.exists?(filename) }
109
-
110
150
  describe "when there is no existing friend with that name" do
111
151
  it "adds the given friend" do
112
152
  stub_friends(friends) do
113
153
  subject
114
- introvert.list_friends.must_include new_friend_name
154
+ introvert.list_friends(location_name: nil).
155
+ must_include new_friend_name
115
156
  end
116
157
  end
117
158
 
@@ -133,10 +174,57 @@ describe Friends::Introvert do
133
174
  end
134
175
  end
135
176
 
177
+ describe "#add_location" do
178
+ let(:new_location_name) { "Peru" }
179
+ subject { introvert.add_location(name: new_location_name) }
180
+
181
+ describe "when there is no existing location with that name" do
182
+ it "adds the given location" do
183
+ stub_locations(locations) do
184
+ subject
185
+ introvert.list_locations.must_include new_location_name
186
+ end
187
+ end
188
+
189
+ it "returns the location added" do
190
+ stub_locations(locations) do
191
+ subject.name.must_equal new_location_name
192
+ end
193
+ end
194
+ end
195
+
196
+ describe "when there is an existing location with that name" do
197
+ let(:new_location_name) { locations.first.name }
198
+
199
+ it "raises an error" do
200
+ stub_locations(locations) do
201
+ proc { subject }.must_raise Friends::FriendsError
202
+ end
203
+ end
204
+ end
205
+ end
206
+
207
+ describe "#list_locations" do
208
+ subject { introvert.list_locations }
209
+
210
+ it "lists all locations" do
211
+ stub_locations(locations) do
212
+ subject.must_equal locations.map(&:name)
213
+ end
214
+ end
215
+ end
216
+
136
217
  describe "#list_activities" do
137
- subject { introvert.list_activities(limit: limit, with: with) }
218
+ subject do
219
+ introvert.list_activities(
220
+ limit: limit,
221
+ with: with,
222
+ location_name: location_name
223
+ )
224
+ end
138
225
  let(:limit) { nil }
139
226
  let(:with) { nil }
227
+ let(:location_name) { nil }
140
228
 
141
229
  describe "when the limit is lower than the number of activities" do
142
230
  let(:limit) { 1 }
@@ -226,6 +314,74 @@ describe Friends::Introvert do
226
314
  end
227
315
  end
228
316
  end
317
+
318
+ describe "when not filtering by a location" do
319
+ let(:location_name) { nil }
320
+
321
+ it "lists the activities" do
322
+ stub_activities(activities) do
323
+ subject.must_equal activities.map(&:display_text)
324
+ end
325
+ end
326
+ end
327
+
328
+ describe "when filtering by part of a location name" do
329
+ let(:location_name) { "City" }
330
+
331
+ describe "when there is more than one location match" do
332
+ let(:locations) do
333
+ [
334
+ Friends::Location.new(name: "New York City"),
335
+ Friends::Location.new(name: "Kansas City")
336
+ ]
337
+ end
338
+
339
+ it "raises an error" do
340
+ stub_friends(friends) do
341
+ stub_locations(locations) do
342
+ stub_activities(activities) do
343
+ proc { subject }.must_raise Friends::FriendsError
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
349
+
350
+ describe "when there are no location matches" do
351
+ let(:locations) { [Friends::Location.new(name: "Atantis")] }
352
+
353
+ it "raises an error" do
354
+ stub_friends(friends) do
355
+ stub_locations(locations) do
356
+ stub_activities(activities) do
357
+ proc { subject }.must_raise Friends::FriendsError
358
+ end
359
+ end
360
+ end
361
+ end
362
+ end
363
+
364
+ describe "when there is exactly one location match" do
365
+ let(:location_name) { "Atlantis" }
366
+ let(:activities) do
367
+ [
368
+ Friends::Activity.new(str: "Swimming near _Atlantis_."),
369
+ Friends::Activity.new(str: "Swimming somewhere else.")
370
+ ]
371
+ end
372
+
373
+ it "filters the activities by that location" do
374
+ stub_friends(friends) do
375
+ stub_locations(locations) do
376
+ stub_activities(activities) do
377
+ # Only one activity has that friend.
378
+ subject.must_equal activities[0..0].map(&:display_text)
379
+ end
380
+ end
381
+ end
382
+ end
383
+ end
384
+ end
229
385
  end
230
386
 
231
387
  describe "#add_activity" do
@@ -233,9 +389,6 @@ describe Friends::Introvert do
233
389
  let(:activity_description) { "Snorkeling with **Betsy Ross**." }
234
390
  subject { introvert.add_activity(serialization: activity_serialization) }
235
391
 
236
- # Delete the file that is created each time.
237
- after { File.delete(filename) if File.exists?(filename) }
238
-
239
392
  it "adds the given activity" do
240
393
  stub_friends(friends) do
241
394
  subject
@@ -293,14 +446,101 @@ describe Friends::Introvert do
293
446
  end
294
447
  end
295
448
 
449
+ describe "#rename_location" do
450
+ subject do
451
+ introvert.rename_location(old_name: old_name, new_name: new_name)
452
+ end
453
+ let(:old_name) { "Paris" }
454
+ let(:new_name) { "Paris, France" }
455
+
456
+ let(:activities) do
457
+ [
458
+ Friends::Activity.new(str: "Dining in _Paris_."),
459
+ Friends::Activity.new(str: "Falling in love in _Paris_."),
460
+ Friends::Activity.new(str: "Swimming near _Atlantis_.")
461
+ ]
462
+ end
463
+ let(:locations) do
464
+ [
465
+ Friends::Location.new(name: "Paris"),
466
+ Friends::Location.new(name: "Atlantis")
467
+ ]
468
+ end
469
+
470
+ it "replaces old name within activities to the new name" do
471
+ stub_locations(locations) do
472
+ stub_activities(activities) do
473
+ subject
474
+ introvert.activities.map do |activity|
475
+ activity.description.include? new_name
476
+ end.must_equal [true, true, false]
477
+ end
478
+ end
479
+ end
480
+
481
+ describe "when there are friends at the location" do
482
+ let(:friends) do
483
+ [
484
+ Friends::Friend.new(name: "Jacques Cousteau", location_name: "Paris"),
485
+ Friends::Friend.new(name: "Marie Antoinette", location_name: "Paris"),
486
+ Friends::Friend.new(name: "Julius Caesar", location_name: "Rome")
487
+ ]
488
+ end
489
+
490
+ it "updates their locations" do
491
+ stub_locations(locations) do
492
+ stub_friends(friends) do
493
+ subject
494
+ introvert.friends.map do |friend|
495
+ friend.location_name == new_name
496
+ end.must_equal [true, true, false]
497
+ end
498
+ end
499
+ end
500
+ end
501
+
502
+ describe "when given names with leading and trailing spaces" do
503
+ let(:new_name) { " Paris, France " }
504
+ let(:old_name) { " Paris " }
505
+ subject do
506
+ introvert.rename_location(old_name: old_name, new_name: new_name)
507
+ end
508
+
509
+ it "correctly strips the spaces" do
510
+ stub_locations(locations) do
511
+ stub_activities(activities) do
512
+ subject
513
+ introvert.activities.map do |activity|
514
+ activity.description.include? new_name
515
+ end.must_equal [true, true, false]
516
+ end
517
+ end
518
+ end
519
+ end
520
+ end
521
+
522
+ describe "#set_location" do
523
+ subject do
524
+ introvert.set_location(
525
+ name: friend_names.first,
526
+ location_name: locations.first.name
527
+ )
528
+ end
529
+
530
+ it "returns the modified friend" do
531
+ stub_friends(friends) do
532
+ stub_locations(locations) do
533
+ subject.must_equal friends.first
534
+ end
535
+ end
536
+ end
537
+ end
538
+
296
539
  describe "#add_nickname" do
297
540
  subject do
298
541
  introvert.add_nickname(name: friend_names.first, nickname: "The Dude")
299
542
  end
300
543
 
301
- # Delete the file that is created each time.
302
- after { File.delete(filename) if File.exists?(filename) }
303
-
304
544
  it "returns the modified friend" do
305
545
  stub_friends(friends) do
306
546
  subject.must_equal friends.first
@@ -313,9 +553,6 @@ describe Friends::Introvert do
313
553
  introvert.remove_nickname(name: "Jeff", nickname: "The Dude")
314
554
  end
315
555
 
316
- # Delete the file that is created each time.
317
- after { File.delete(filename) if File.exists?(filename) }
318
-
319
556
  it "returns the modified friend" do
320
557
  friend = Friends::Friend.new(name: "Jeff",
321
558
  nickname_str: "a.k.a. The Dude")
@@ -357,28 +594,61 @@ describe Friends::Introvert do
357
594
  end
358
595
 
359
596
  describe "#suggest" do
360
- subject { introvert.suggest }
597
+ subject { introvert.suggest(location_name: location_name) }
361
598
 
362
- it "returns distant, moderate, and close friends" do
363
- stub_friends(friends) do
364
- stub_activities(activities) do
365
- subject.must_equal(
366
- distant: ["George Washington Carver"],
367
- moderate: [],
368
- close: ["Betsy Ross"]
369
- )
599
+ describe "when no location name is passed" do
600
+ let(:location_name) { nil }
601
+
602
+ it "returns distant, moderate, and close friends" do
603
+ stub_friends(friends) do
604
+ stub_activities(activities) do
605
+ subject.must_equal(
606
+ distant: ["George Washington Carver"],
607
+ moderate: [],
608
+ close: ["Betsy Ross"]
609
+ )
610
+ end
611
+ end
612
+ end
613
+
614
+ it "doesn't choke when there are no friends" do
615
+ stub_friends([]) do
616
+ stub_activities([]) do
617
+ subject.must_equal(
618
+ distant: [],
619
+ moderate: [],
620
+ close: []
621
+ )
622
+ end
370
623
  end
371
624
  end
372
625
  end
373
626
 
374
- it "doesn't choke when there are no friends" do
375
- stub_friends([]) do
376
- stub_activities([]) do
377
- subject.must_equal(
378
- distant: [],
379
- moderate: [],
380
- close: []
381
- )
627
+ describe "when a location name is passed" do
628
+ let(:location_name) { "USA" }
629
+
630
+ it "returns distant, moderate, and close friends" do
631
+ friends.first.location_name = location_name
632
+ stub_friends(friends) do
633
+ stub_activities(activities) do
634
+ subject.must_equal(
635
+ distant: ["George Washington Carver"],
636
+ moderate: [],
637
+ close: []
638
+ )
639
+ end
640
+ end
641
+ end
642
+
643
+ it "doesn't choke when there are no friends" do
644
+ stub_friends([]) do
645
+ stub_activities([]) do
646
+ subject.must_equal(
647
+ distant: [],
648
+ moderate: [],
649
+ close: []
650
+ )
651
+ end
382
652
  end
383
653
  end
384
654
  end
@@ -431,12 +701,14 @@ describe Friends::Introvert do
431
701
  it "returns a hash of months and frequencies" do
432
702
  stub_friends(friends) do
433
703
  stub_activities(activities) do
434
- subject.must_equal({
435
- "Jan 2016" => 1,
436
- "Feb 2016" => 1,
437
- "Mar 2016" => 0,
438
- "Apr 2016" => 1
439
- })
704
+ subject.must_equal(
705
+ {
706
+ "Jan 2016" => 1,
707
+ "Feb 2016" => 1,
708
+ "Mar 2016" => 0,
709
+ "Apr 2016" => 1
710
+ }
711
+ )
440
712
  end
441
713
  end
442
714
  end
@@ -448,11 +720,13 @@ describe Friends::Introvert do
448
720
  it "returns a hash of months and frequencies" do
449
721
  stub_friends(friends) do
450
722
  stub_activities(activities) do
451
- subject.must_equal({
452
- "Feb 2016" => 1,
453
- "Mar 2016" => 0,
454
- "Apr 2016" => 1
455
- })
723
+ subject.must_equal(
724
+ {
725
+ "Feb 2016" => 1,
726
+ "Mar 2016" => 0,
727
+ "Apr 2016" => 1
728
+ }
729
+ )
456
730
  end
457
731
  end
458
732
  end