friends 0.16 → 0.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -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