friends 0.29 → 0.30

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 266cfedd5b0654ca5ebd434c11ead3d8c21d4e9e
4
- data.tar.gz: 76d290e42cc9babe0dcfe3dd9419dded6ca4825d
3
+ metadata.gz: 81e378aa8d3e1a7285adcb3f92cc91977c22eca2
4
+ data.tar.gz: f48b3ccd7d4006679c7b072b06a980432c759a6c
5
5
  SHA512:
6
- metadata.gz: 41e311c6cd3f8dc4a0c9e86d5268badad683731307626f6f50ef33eaf15edfc930754adce617f2934262b6915caa87b3167b138741b3e6b99025d0c4cc542a06
7
- data.tar.gz: e838474558ec1a065cd7d72a828fb6073adafac32a6aec23b4bc6e930063f5838e55129d9a6d82d01bf0236a79777db936a31a32b15104fce83cdd3c146e1c5c
6
+ metadata.gz: ee11daf225f5c245b68a732267b0fafd7041d478d8cff7d68860f9b50a71f9a3db51de2edd4a7dac723a6db5c5c26045a697a21bc7215acc770bed3a2390ee10
7
+ data.tar.gz: e47d850e7cc62ea74a0c212f0315de2cc5bd1eb72f331526ccee67dd39d7599b091a546770d14ba2af7132f929ab8d9076f61b28cb8a68a36432ccda3d481f56
data/.gitignore CHANGED
@@ -17,3 +17,4 @@ ideas.txt
17
17
  TODO.txt
18
18
  .DS_Store
19
19
  .byebug_history
20
+ .ruby-version
@@ -125,6 +125,9 @@ Lambda:
125
125
  LambdaCall:
126
126
  Enabled: false
127
127
 
128
+ Layout/IndentHeredoc:
129
+ Enabled: false
130
+
128
131
  LineEndConcatenation:
129
132
  Enabled: false
130
133
 
@@ -235,6 +238,9 @@ StringLiterals:
235
238
  Style/MultilineBlockChain:
236
239
  Enabled: false
237
240
 
241
+ Style/SymbolArray:
242
+ EnforcedStyle: brackets
243
+
238
244
  VariableInterpolation:
239
245
  Enabled: false
240
246
 
@@ -5,10 +5,7 @@ rvm:
5
5
  - 2.3.0
6
6
  - 2.4.0
7
7
  script:
8
- - bundle exec rake test
9
- - bundle exec rubocop
10
- addons:
11
- code_climate:
12
- repo_token: d744a74c96e3e5c763ed776709aff0662ac2f3e8274c01e439e09b38c8be4225
8
+ - bundle exec rake test
9
+ - bundle exec rubocop
13
10
  notifications:
14
11
  email: false
@@ -1,5 +1,20 @@
1
1
  # Change Log
2
2
 
3
+ ## [v0.30](https://github.com/JacobEvelyn/friends/tree/v0.30) (2017-05-30)
4
+ [Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.29...v0.30)
5
+
6
+ **Implemented enhancements:**
7
+
8
+ - Code coverage in README is too low [\#163](https://github.com/JacobEvelyn/friends/issues/163)
9
+ - Improve display of favorites for ties [\#158](https://github.com/JacobEvelyn/friends/issues/158)
10
+ - Filter activities based on more than one friend/tag/etc. [\#88](https://github.com/JacobEvelyn/friends/issues/88)
11
+
12
+ **Merged pull requests:**
13
+
14
+ - Be able to filter output by more than one friend or tag [\#168](https://github.com/JacobEvelyn/friends/pull/168) ([JacobEvelyn](https://github.com/JacobEvelyn))
15
+ - Improve display of favorites for ties [\#165](https://github.com/JacobEvelyn/friends/pull/165) ([JacobEvelyn](https://github.com/JacobEvelyn))
16
+ - Correct code coverage calculations [\#164](https://github.com/JacobEvelyn/friends/pull/164) ([JacobEvelyn](https://github.com/JacobEvelyn))
17
+
3
18
  ## [v0.29](https://github.com/JacobEvelyn/friends/tree/v0.29) (2017-03-18)
4
19
  [Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.28...v0.29)
5
20
 
@@ -6,8 +6,8 @@ merge this change:
6
6
  - [ ] The code in these changes works correctly.
7
7
  - [ ] Code has tests as appropriate.
8
8
  - [ ] Code has been reviewed by @JacobEvelyn.
9
- - [ ] All tests pass on TravisCI.
10
- - [ ] Rubocop reports no issues on TravisCI.
9
+ - [ ] All tests pass on Travis CI.
10
+ - [ ] Rubocop reports no issues on Travis CI.
11
11
  - [ ] The `README.md` file is updated as appropriate.
12
12
 
13
13
  Don't worry—this list will get checked off in no time!
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/friends.svg)](https://badge.fury.io/rb/friends) [![Dependency Status](https://gemnasium.com/badges/github.com/JacobEvelyn/friends.svg)](https://gemnasium.com/github.com/JacobEvelyn/friends)
2
- [![Code Climate](https://codeclimate.com/github/JacobEvelyn/friends/badges/gpa.svg)](https://codeclimate.com/github/JacobEvelyn/friends) [![Test Coverage](https://codeclimate.com/github/JacobEvelyn/friends/badges/coverage.svg)](https://codeclimate.com/github/JacobEvelyn/friends) [![Build Status](https://travis-ci.org/JacobEvelyn/friends.svg?branch=master)](https://travis-ci.org/JacobEvelyn/friends) [![Inline docs](http://inch-ci.org/github/JacobEvelyn/friends.png)](http://inch-ci.org/github/JacobEvelyn/friends) [![ghit.me](https://ghit.me/badge.svg?repo=JacobEvelyn/friends)](https://ghit.me/repo/JacobEvelyn/friends)
2
+ [![Coverage Status](https://coveralls.io/repos/github/JacobEvelyn/friends/badge.svg)](https://coveralls.io/github/JacobEvelyn/friends) [![Build Status](https://travis-ci.org/JacobEvelyn/friends.svg?branch=master)](https://travis-ci.org/JacobEvelyn/friends) [![Inline docs](http://inch-ci.org/github/JacobEvelyn/friends.png)](http://inch-ci.org/github/JacobEvelyn/friends) [![ghit.me](https://ghit.me/badge.svg?repo=JacobEvelyn/friends)](https://ghit.me/repo/JacobEvelyn/friends)
3
3
 
4
4
  # `friends`
5
5
 
@@ -343,6 +343,13 @@ Jan 2015 |█████
343
343
  Feb 2015 |███
344
344
  ```
345
345
 
346
+ Or a certain group of friends:
347
+
348
+ ```bash
349
+ $ friends graph --with George --with Grace
350
+ Jan 2015 |█
351
+ ```
352
+
346
353
  Or graph only activities with a certain tag:
347
354
 
348
355
  ```bash
@@ -353,6 +360,13 @@ Jan 2015 |
353
360
  Feb 2015 |███
354
361
  ```
355
362
 
363
+ Or with multiple tags:
364
+
365
+ ```bash
366
+ $ friends graph --tagged @fun --tagged @work
367
+ Jul 2017 |█
368
+ ```
369
+
356
370
  Or graph only activities in a certain location:
357
371
 
358
372
  ```bash
@@ -443,6 +457,13 @@ $ friends list activities --with George
443
457
  2014-11-15: Talked to George Washington Carver on the phone for an hour.
444
458
  ```
445
459
 
460
+ Or only filter activities done with a group of friends:
461
+
462
+ ```bash
463
+ $ friends list activities --with George --with Grace
464
+ 2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food
465
+ ```
466
+
446
467
  Or filter your activities by location:
447
468
 
448
469
  ```bash
@@ -457,16 +478,23 @@ $ friends list activities --tagged food
457
478
  2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food
458
479
  ```
459
480
 
481
+ Or use more than one tag:
482
+
483
+ ```bash
484
+ $ friends list activities --tagged @fun --tagged @work
485
+ 2017-07-04: Summer picnic with @work colleagues. @fun
486
+ ```
487
+
460
488
  Or by date:
461
489
 
462
490
  ```bash
463
- $ friends graph --since 'December 31st 2014'
491
+ $ friends list activities --since 'December 31st 2014'
464
492
  2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food
465
493
  2014-12-31: Celebrated the new year with Marie Curie in New York City. @partying
466
494
  ```
467
495
 
468
496
  ```bash
469
- $ friends graph --until 'December 31st 2014'
497
+ $ friends list activities --until 'December 31st 2014'
470
498
  2014-12-31: Celebrated the new year with Marie Curie in New York City. @partying
471
499
  2014-11-15: Talked to George Washington Carver on the phone for an hour.
472
500
  ```
@@ -474,7 +502,7 @@ $ friends graph --until 'December 31st 2014'
474
502
  And you can mix and match these options to your heart's content:
475
503
 
476
504
  ```bash
477
- $ friends list activities --tagged food --with Grace
505
+ $ friends list activities --tagged food --with Grace --with George
478
506
  2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food
479
507
  ```
480
508
 
@@ -487,7 +515,7 @@ $ friends list favorite friends
487
515
  Your favorite friends:
488
516
  1. George Washington Carver (2 activities)
489
517
  2. Grace Hopper (1)
490
- 3. Marie Curie (1)
518
+ 3. Marie Curie (0)
491
519
  ```
492
520
 
493
521
  You can specify a number of favorites to show:
@@ -508,7 +536,7 @@ $ friends list favorite locations
508
536
  Your favorite locations:
509
537
  1. Atlantis (2 activities)
510
538
  2. Paris (1)
511
- 3. London (1)
539
+ 3. London (0)
512
540
  ```
513
541
 
514
542
  You can specify a number of favorites to show:
@@ -555,6 +583,13 @@ Grace Hopper
555
583
  Marie Curie
556
584
  ```
557
585
 
586
+ You can even use more than one tag to further narrow down the list:
587
+
588
+ ```bash
589
+ $ friends list friends --tagged science --tagged navy
590
+ Grace Hopper
591
+ ```
592
+
558
593
  #### `list tags`
559
594
 
560
595
  Lists all tags you've used, in alphabetical order:
@@ -1,6 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ if ENV["TRAVIS"] == "true"
5
+ require "simplecov"
6
+ SimpleCov.formatter = SimpleCov::Formatter::SimpleFormatter
7
+ SimpleCov.command_name Process.pid
8
+ SimpleCov.start
9
+ end
10
+
4
11
  require "gli"
5
12
  require "paint"
6
13
  require "readline"
@@ -30,11 +30,10 @@ Gem::Specification.new do |spec|
30
30
  spec.add_dependency "semverse", "~> 1.2"
31
31
 
32
32
  spec.add_development_dependency "bundler", "~> 1.6"
33
- spec.add_development_dependency "codeclimate-test-reporter", "~> 0.5"
33
+ spec.add_development_dependency "coveralls", "~> 0.8"
34
34
  spec.add_development_dependency "minitest", "~> 5.5"
35
- spec.add_development_dependency "minitest-parallel_fork", "~> 1.0"
36
35
  spec.add_development_dependency "minitest-proveit", "~> 1.0"
37
- spec.add_development_dependency "overcommit", "~> 0.34"
38
36
  spec.add_development_dependency "rake", "~> 11.2"
39
- spec.add_development_dependency "rubocop", "~> 0.40"
37
+ spec.add_development_dependency "rubocop", "~> 0.49"
38
+ spec.add_development_dependency "simplecov", "~> 0.14"
40
39
  end
@@ -5,7 +5,8 @@ command :graph do |graph|
5
5
  graph.flag [:with],
6
6
  arg_name: "NAME",
7
7
  desc: "Graph activities with the given friend",
8
- type: Stripped
8
+ type: Stripped,
9
+ multiple: true
9
10
 
10
11
  graph.flag [:in],
11
12
  arg_name: "LOCATION",
@@ -15,7 +16,8 @@ command :graph do |graph|
15
16
  graph.flag [:tagged],
16
17
  arg_name: "@TAG",
17
18
  desc: "Graph activities with the given tag",
18
- type: Tag
19
+ type: Tag,
20
+ multiple: true
19
21
 
20
22
  graph.flag [:since],
21
23
  arg_name: "DATE",
@@ -12,7 +12,8 @@ command :list do |list|
12
12
  list_friends.flag [:tagged],
13
13
  arg_name: "@TAG",
14
14
  desc: "List only friends with the given tag",
15
- type: Tag
15
+ type: Tag,
16
+ multiple: true
16
17
 
17
18
  list_friends.switch [:verbose],
18
19
  negatable: false,
@@ -38,7 +39,8 @@ command :list do |list|
38
39
  list_activities.flag [:with],
39
40
  arg_name: "NAME",
40
41
  desc: "List only activities with the given friend",
41
- type: Stripped
42
+ type: Stripped,
43
+ multiple: true
42
44
 
43
45
  list_activities.flag [:in],
44
46
  arg_name: "LOCATION",
@@ -48,7 +50,8 @@ command :list do |list|
48
50
  list_activities.flag [:tagged],
49
51
  arg_name: "@TAG",
50
52
  desc: "List only activities with the given tag",
51
- type: Tag
53
+ type: Tag,
54
+ multiple: true
52
55
 
53
56
  list_activities.flag [:since],
54
57
  arg_name: "DATE",
@@ -101,18 +104,7 @@ command :list do |list|
101
104
  type: Integer
102
105
 
103
106
  list_favorite_friends.action do |_, options|
104
- favorites = @introvert.list_favorite_friends(limit: options[:limit])
105
-
106
- if options[:limit] == 1
107
- puts "Your best friend is #{favorites.first}"
108
- else
109
- puts "Your favorite friends:"
110
-
111
- num_str_size = favorites.size.to_s.size + 1
112
- favorites.each.with_index(1) do |name, rank|
113
- puts "#{"#{rank}.".ljust(num_str_size)} #{name}"
114
- end
115
- end
107
+ @introvert.list_favorite_friends(limit: options[:limit])
116
108
  end
117
109
  end
118
110
 
@@ -125,18 +117,7 @@ command :list do |list|
125
117
  type: Integer
126
118
 
127
119
  list_favorite_locations.action do |_, options|
128
- favorites = @introvert.list_favorite_locations(limit: options[:limit])
129
-
130
- if options[:limit] == 1
131
- puts "Your favorite location is #{favorites.first}"
132
- else
133
- puts "Your favorite locations:"
134
-
135
- num_str_size = favorites.size.to_s.size + 1
136
- favorites.each.with_index(1) do |name, rank|
137
- puts "#{"#{rank}.".ljust(num_str_size)} #{name}"
138
- end
139
- end
120
+ @introvert.list_favorite_locations(limit: options[:limit])
140
121
  end
141
122
  end
142
123
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Graphs activities by month
3
4
 
4
5
  module Friends
@@ -186,8 +186,8 @@ module Friends
186
186
  # List all friend names in the friends file.
187
187
  # @param location_name [String] the name of a location to filter by, or nil
188
188
  # for unfiltered
189
- # @param tagged [String] the name of a tag to filter by (of the form:
190
- # "@tag"), or nil for unfiltered
189
+ # @param tagged [Array<String>] the names of tags to filter by, or empty for
190
+ # unfiltered
191
191
  # @param verbose [Boolean] true iff we should output friend names with
192
192
  # nicknames, locations, and tags; false for names only
193
193
  # @return [Array] a list of all friend names
@@ -200,8 +200,12 @@ module Friends
200
200
  fs = fs.select { |friend| friend.location_name == location.name }
201
201
  end
202
202
 
203
- # Filter by tag if one is passed.
204
- fs = fs.select { |friend| friend.tags.include? tagged } if tagged
203
+ # Filter by tag if param is passed.
204
+ unless tagged.empty?
205
+ fs = fs.select do |friend|
206
+ tagged.all? { |tag| friend.tags.include? tag }
207
+ end
208
+ end
205
209
 
206
210
  verbose ? fs.map(&:to_s) : fs.map(&:name)
207
211
  end
@@ -225,12 +229,12 @@ module Friends
225
229
  # List all activity details.
226
230
  # @param limit [Integer] the number of activities to return, or nil for no
227
231
  # limit
228
- # @param with [String] the name of a friend to filter by, or nil for
232
+ # @param with [Array<String>] the names of friends to filter by, or empty for
233
+ # unfiltered
234
+ # @param location_name [String] the name of a location to filter by, or
235
+ # nil for unfiltered
236
+ # @param tagged [Array<String>] the names of tags to filter by, or empty for
229
237
  # unfiltered
230
- # @param location_name [String] the name of a location to filter by, or nil
231
- # for unfiltered
232
- # @param tagged [String] the name of a tag to filter by (of the form:
233
- # "@tag"), or nil for unfiltered
234
238
  # @param since_date [Date] a date on or after which to find activities, or nil for unfiltered
235
239
  # @param until_date [Date] a date before or on which to find activities, or nil for unfiltered
236
240
  # @return [Array] a list of all activity text values
@@ -294,12 +298,12 @@ module Friends
294
298
  # The keys of the hash are all of the months (inclusive) between the first
295
299
  # and last month in which activities have been recorded.
296
300
  #
297
- # @param with [String] the name of a friend to filter by, or nil for
301
+ # @param with [Array<String>] the names of friends to filter by, or empty for
302
+ # unfiltered
303
+ # @param location_name [String] the name of a location to filter by, or
304
+ # nil for unfiltered
305
+ # @param tagged [Array<String>] the names of tags to filter by, or empty for
298
306
  # unfiltered
299
- # @param location_name [String] the name of a location to filter by, or nil
300
- # for unfiltered
301
- # @param tagged [String] the name of a tag to filter by (of the form:
302
- # "@tag"), or nil for unfiltered
303
307
  # @param since_date [Date] a date on or after which to find activities, or nil for unfiltered
304
308
  # @param until_date [Date] a date before or on which to find activities, or nil for unfiltered
305
309
  # @return [Hash{String => Integer}]
@@ -451,11 +455,11 @@ module Friends
451
455
  private
452
456
 
453
457
  # Filter activities by friend, location and tag
454
- # @param with [String] the name of a friend to filter by, or nil for
458
+ # @param with [Array<String>] the names of friends to filter by, or empty for
455
459
  # unfiltered
456
- # @param location_name [String] the name of a location to filter by, or nil
457
- # for unfiltered
458
- # @param tagged [String] the name of a tag to filter by, or nil for
460
+ # @param location_name [String] the name of a location to filter by, or
461
+ # nil for unfiltered
462
+ # @param tagged [Array<String>] the names of tags to filter by, or empty for
459
463
  # unfiltered
460
464
  # @param since_date [Date] a date on or after which to find activities, or nil for unfiltered
461
465
  # @param until_date [Date] a date before or on which to find activities, or nil for unfiltered
@@ -466,9 +470,11 @@ module Friends
466
470
  acts = @activities
467
471
 
468
472
  # Filter by friend name if argument is passed.
469
- unless with.nil?
470
- friend = thing_with_name_in(:friend, with)
471
- acts = acts.select { |act| act.includes_friend?(friend) }
473
+ unless with.empty?
474
+ friends = with.map { |name| thing_with_name_in(:friend, name) }
475
+ acts = acts.select do |act|
476
+ friends.all? { |friend| act.includes_friend?(friend) }
477
+ end
472
478
  end
473
479
 
474
480
  # Filter by location name if argument is passed.
@@ -478,7 +484,11 @@ module Friends
478
484
  end
479
485
 
480
486
  # Filter by tag if argument is passed.
481
- acts = acts.select { |act| act.includes_tag?(tagged) } unless tagged.nil?
487
+ unless tagged.empty?
488
+ acts = acts.select do |act|
489
+ tagged.all? { |tag| act.includes_tag?(tag) }
490
+ end
491
+ end
482
492
 
483
493
  # Filter by date if arguments are passed.
484
494
  acts = acts.select { |act| act.date >= since_date } unless since_date.nil?
@@ -504,15 +514,42 @@ module Friends
504
514
  -thing.n_activities
505
515
  end.take(limit) # Trim the list.
506
516
 
507
- max_str_size = results.map(&:name).map(&:size).max
508
- results.map.with_index(0) do |thing, index|
509
- name = thing.name.ljust(max_str_size)
510
- n = thing.n_activities
511
- if index.zero?
512
- label = n == 1 ? " activity" : " activities"
517
+ if results.size == 1
518
+ favorite = results.first
519
+ puts "Your favorite #{type} is "\
520
+ "#{favorite.name} "\
521
+ "(#{favorite.n_activities} "\
522
+ "#{favorite.n_activities == 1 ? 'activity' : 'activities'})"
523
+ else
524
+ puts "Your favorite #{type}s:"
525
+
526
+ max_str_size = results.map(&:name).map(&:size).max
527
+
528
+ grouped_results = results.group_by(&:n_activities)
529
+
530
+ rank = 1
531
+ first = true
532
+ data = grouped_results.each.with_object([]) do |(n_activities, things), arr|
533
+ things.each do |thing|
534
+ name = thing.name.ljust(max_str_size)
535
+ if first
536
+ label = n_activities == 1 ? " activity" : " activities"
537
+ first = false
538
+ end
539
+ str = "#{name} (#{n_activities}#{label})"
540
+
541
+ arr << [rank, str]
542
+ end
543
+ rank += things.size
544
+ end
545
+
546
+ # We need to use `data.last.first` instead of `rank` to determine the size
547
+ # of the numbering prefix because `rank` will simply be the size of all
548
+ # elements, which may be too large if the last element in the list is a tie.
549
+ num_str_size = data.last.first.to_s.size + 1 unless data.empty?
550
+ data.each do |ranking, str|
551
+ puts "#{"#{ranking}.".ljust(num_str_size)} #{str}"
513
552
  end
514
- parenthetical = "(#{n}#{label})"
515
- "#{name} #{parenthetical}"
516
553
  end
517
554
  end
518
555
 
@@ -24,7 +24,7 @@ module Serializable
24
24
  args = match.names.
25
25
  map { |name| { name.to_sym => match[name.to_sym] } }.
26
26
  reduce(:merge).
27
- select { |_, v| !v.nil? }
27
+ reject { |_, v| v.nil? }
28
28
 
29
29
  new(args)
30
30
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Friends
4
- VERSION = "0.29"
4
+ VERSION = "0.30"
5
5
  end
@@ -90,6 +90,16 @@ Jan 2015 |█
90
90
  OUTPUT
91
91
  end
92
92
  end
93
+
94
+ describe "when more than one friend name is passed" do
95
+ subject { run_cmd("graph --with #{friend_name1} --with #{friend_name2}") }
96
+ let(:friend_name1) { "george" }
97
+ let(:friend_name2) { "grace" }
98
+
99
+ it "matches all friends case-insensitively" do
100
+ stdout_only "Jan 2015 |█"
101
+ end
102
+ end
93
103
  end
94
104
 
95
105
  describe "--tagged" do
@@ -110,6 +120,30 @@ Oct 2015 |
110
120
  Nov 2015 |█
111
121
  OUTPUT
112
122
  end
123
+
124
+ describe "when more than one tag is passed" do
125
+ subject { run_cmd("graph --tagged #{tag1} --tagged #{tag2}") }
126
+ let(:tag1) { "food" }
127
+ let(:tag2) { "partying" }
128
+ let(:content) do
129
+ <<-FILE
130
+ ### Activities:
131
+ - 2015-01-04: Got lunch with **Grace Hopper** and **George Washington Carver**. @food
132
+ - 2015-11-01: **Grace Hopper** and I went to _Marie's Diner_. George had to cancel at the last minute. @food
133
+ - 2014-11-15: Talked to **George Washington Carver** on the phone for an hour.
134
+ - 2014-12-31: Celebrated the new year in _Paris_ with **Marie Curie**. @partying @food
135
+
136
+ ### Friends:
137
+ - George Washington Carver
138
+ - Marie Curie [Atlantis] @science
139
+ - Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
140
+ FILE
141
+ end
142
+
143
+ it "matches all tags case-sensitively" do
144
+ stdout_only "Dec 2014 |█"
145
+ end
146
+ end
113
147
  end
114
148
 
115
149
  describe "--since" do
@@ -97,6 +97,16 @@ clean_describe "list activities" do
97
97
  stdout_only "2014-12-31: Celebrated the new year in Paris with Marie Curie. @partying"
98
98
  end
99
99
  end
100
+
101
+ describe "when more than one friend name is passed" do
102
+ subject { run_cmd("list activities --with #{friend_name1} --with #{friend_name2}") }
103
+ let(:friend_name1) { "george" }
104
+ let(:friend_name2) { "grace" }
105
+
106
+ it "matches all friends case-insensitively" do
107
+ stdout_only "2015-01-04: Got lunch with Grace Hopper and George Washington Carver. @food"
108
+ end
109
+ end
100
110
  end
101
111
 
102
112
  describe "--tagged" do
@@ -108,6 +118,32 @@ clean_describe "list activities" do
108
118
  2015-11-01: Grace Hopper and I went to Marie's Diner. George had to cancel at the last minute. @food
109
119
  OUTPUT
110
120
  end
121
+
122
+ describe "when more than one tag is passed" do
123
+ subject { run_cmd("list activities --tagged #{tag1} --tagged #{tag2}") }
124
+ let(:tag1) { "food" }
125
+ let(:tag2) { "partying" }
126
+ let(:content) do
127
+ <<-FILE
128
+ ### Activities:
129
+ - 2015-01-04: Got lunch with **Grace Hopper** and **George Washington Carver**. @food
130
+ - 2015-11-01: **Grace Hopper** and I went to _Marie's Diner_. George had to cancel at the last minute. @food
131
+ - 2014-11-15: Talked to **George Washington Carver** on the phone for an hour.
132
+ - 2014-12-31: Celebrated the new year in _Paris_ with **Marie Curie**. @partying @food
133
+
134
+ ### Friends:
135
+ - George Washington Carver
136
+ - Marie Curie [Atlantis] @science
137
+ - Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
138
+ FILE
139
+ end
140
+
141
+ it "matches all tags case-sensitively" do
142
+ stdout_only(
143
+ "2014-12-31: Celebrated the new year in Paris with Marie Curie. @partying @food"
144
+ )
145
+ end
146
+ end
111
147
  end
112
148
 
113
149
  describe "--since" do
@@ -45,6 +45,69 @@ Your favorite friends:
45
45
  OUTPUT
46
46
  end
47
47
 
48
+ describe "when friends are tied for the same number of activities" do
49
+ let(:content) do
50
+ <<-FILE
51
+ ### Activities:
52
+ - 2017-01-01: Did something with **Friend A**.
53
+ - 2017-01-01: Did something with **Friend A**.
54
+ - 2017-01-01: Did something with **Friend B**.
55
+ - 2017-01-01: Did something with **Friend B**.
56
+ - 2017-01-01: Did something with **Friend C**.
57
+ - 2017-01-01: Did something with **Friend D**.
58
+ - 2017-01-01: Did something with **Friend E**.
59
+ - 2017-01-01: Did something with **Friend F**.
60
+ - 2017-01-01: Did something with **Friend G**.
61
+ - 2017-01-01: Did something with **Friend H**.
62
+ - 2017-01-01: Did something with **Friend I**.
63
+ - 2017-01-01: Did something with **Friend J**.
64
+
65
+ ### Friends:
66
+ - Friend A
67
+ - Friend B
68
+ - Friend C
69
+ - Friend D
70
+ - Friend E
71
+ - Friend F
72
+ - Friend G
73
+ - Friend H
74
+ - Friend I
75
+ - Friend J
76
+ FILE
77
+ end
78
+
79
+ it "uses tied ranks" do
80
+ subject[:stderr].must_equal ""
81
+ subject[:status].must_equal 0
82
+
83
+ lines = subject[:stdout].split("\n")
84
+ lines[1].must_match(/1\. Friend (A|B)/)
85
+ lines[2].must_match(/1\. Friend (A|B)/)
86
+ lines[3].must_include "3. Friend"
87
+ end
88
+
89
+ it "only uses the word 'activities' for the first item, even when a tie" do
90
+ subject[:stderr].must_equal ""
91
+ subject[:status].must_equal 0
92
+
93
+ lines = subject[:stdout].split("\n")
94
+ lines[1].must_include "activities"
95
+ lines[2].wont_include "activities"
96
+ end
97
+
98
+ it "indents based on the highest rank number, not the number of friends" do
99
+ subject[:stderr].must_equal ""
100
+ subject[:status].must_equal 0
101
+
102
+ # Since there are 10 friends, a naive implementation would pad our output
103
+ # assuming the (numerically) highest rank is "10." but since the highest
104
+ # rank is a tie, we never display a double-digit rank, so we don't need to
105
+ # pad our output for double digits.
106
+ lines = subject[:stdout].split("\n")
107
+ lines.last.must_include "3. Friend"
108
+ end
109
+ end
110
+
48
111
  describe "--limit" do
49
112
  subject { run_cmd("list favorite friends --limit #{limit}") }
50
113
 
@@ -57,8 +120,27 @@ Your favorite friends:
57
120
 
58
121
  describe "when limit is 1" do
59
122
  let(:limit) { 1 }
60
- it "outputs as a best friend" do
61
- stdout_only "Your best friend is Grace Hopper (3 activities)"
123
+
124
+ it "uses correct friend pluralization" do
125
+ stdout_only "Your favorite friend is Grace Hopper (3 activities)"
126
+ end
127
+
128
+ describe "when favorite friend only has one activity" do
129
+ let(:content) do
130
+ <<-FILE
131
+ ### Activities:
132
+ - 2017-01-01: Did some math with **Grace Hopper**.
133
+
134
+ ### Friends:
135
+ - George Washington Carver
136
+ - Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
137
+ - Marie Curie [Atlantis] @science
138
+ FILE
139
+ end
140
+
141
+ it "uses correct activity pluralization" do
142
+ stdout_only "Your favorite friend is Grace Hopper (1 activity)"
143
+ end
62
144
  end
63
145
  end
64
146
 
@@ -50,6 +50,69 @@ Your favorite locations:
50
50
  OUTPUT
51
51
  end
52
52
 
53
+ describe "when locations are tied for the same number of activities" do
54
+ let(:content) do
55
+ <<-FILE
56
+ ### Activities:
57
+ - 2017-01-01: Did something in _Location A_.
58
+ - 2017-01-01: Did something in _Location A_.
59
+ - 2017-01-01: Did something in _Location B_.
60
+ - 2017-01-01: Did something in _Location B_.
61
+ - 2017-01-01: Did something in _Location C_.
62
+ - 2017-01-01: Did something in _Location D_.
63
+ - 2017-01-01: Did something in _Location E_.
64
+ - 2017-01-01: Did something in _Location F_.
65
+ - 2017-01-01: Did something in _Location G_.
66
+ - 2017-01-01: Did something in _Location H_.
67
+ - 2017-01-01: Did something in _Location I_.
68
+ - 2017-01-01: Did something in _Location J_.
69
+
70
+ ### Locations:
71
+ - Location A
72
+ - Location B
73
+ - Location C
74
+ - Location D
75
+ - Location E
76
+ - Location F
77
+ - Location G
78
+ - Location H
79
+ - Location I
80
+ - Location J
81
+ FILE
82
+ end
83
+
84
+ it "uses tied ranks" do
85
+ subject[:stderr].must_equal ""
86
+ subject[:status].must_equal 0
87
+
88
+ lines = subject[:stdout].split("\n")
89
+ lines[1].must_match(/1\. Location (A|B)/)
90
+ lines[2].must_match(/1\. Location (A|B)/)
91
+ lines[3].must_include "3. Location"
92
+ end
93
+
94
+ it "only uses the word 'activities' for the first item, even when a tie" do
95
+ subject[:stderr].must_equal ""
96
+ subject[:status].must_equal 0
97
+
98
+ lines = subject[:stdout].split("\n")
99
+ lines[1].must_include "activities"
100
+ lines[2].wont_include "activities"
101
+ end
102
+
103
+ it "indents based on the highest rank number, not the number of locations" do
104
+ subject[:stderr].must_equal ""
105
+ subject[:status].must_equal 0
106
+
107
+ # Since there are 10 friends, a naive implementation would pad our output
108
+ # assuming the (numerically) highest rank is "10." but since the highest
109
+ # rank is a tie, we never display a double-digit rank, so we don't need to
110
+ # pad our output for double digits.
111
+ lines = subject[:stdout].split("\n")
112
+ lines.last.must_include "3. Location"
113
+ end
114
+ end
115
+
53
116
  describe "--limit" do
54
117
  subject { run_cmd("list favorite locations --limit #{limit}") }
55
118
 
@@ -62,9 +125,33 @@ Your favorite locations:
62
125
 
63
126
  describe "when limit is 1" do
64
127
  let(:limit) { 1 }
65
- it "outputs as a favorite location" do
128
+
129
+ it "uses correct location pluralization" do
66
130
  stdout_only "Your favorite location is Marie's Diner (2 activities)"
67
131
  end
132
+
133
+ describe "when favorite location only has one activity" do
134
+ let(:content) do
135
+ <<-FILE
136
+ ### Activities:
137
+ - 2017-01-01: Did some math with **Grace Hopper** at _Marie's Diner_.
138
+
139
+ ### Friends:
140
+ - George Washington Carver
141
+ - Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
142
+ - Marie Curie [Atlantis] @science
143
+
144
+ ### Locations:
145
+ - Atlantis
146
+ - Marie's Diner
147
+ - Paris
148
+ FILE
149
+ end
150
+
151
+ it "uses correct activity pluralization" do
152
+ stdout_only "Your favorite location is Marie's Diner (1 activity)"
153
+ end
154
+ end
68
155
  end
69
156
 
70
157
  describe "when limit is greater than 1" do
@@ -71,6 +71,31 @@ Marie Curie
71
71
  Grace Hopper
72
72
  OUTPUT
73
73
  end
74
+
75
+ describe "when more than one tag is passed" do
76
+ subject { run_cmd("list friends --tagged #{tag1} --tagged #{tag2}") }
77
+ let(:tag1) { "science" }
78
+ let(:tag2) { "navy" }
79
+ let(:content) do
80
+ <<-FILE
81
+ ### Activities:
82
+
83
+ ### Friends:
84
+ - George Washington Carver
85
+ - Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
86
+ - Marie Curie [Atlantis] @science
87
+ - Neil Armstrong @navy @science
88
+ - John F. Kennedy @navy
89
+ FILE
90
+ end
91
+
92
+ it "matches all tags case-sensitively" do
93
+ stdout_only <<-OUTPUT
94
+ Grace Hopper
95
+ Neil Armstrong
96
+ OUTPUT
97
+ end
98
+ end
74
99
  end
75
100
  end
76
101
  end
@@ -1,14 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "codeclimate-test-reporter"
4
- CodeClimate::TestReporter.start
3
+ if ENV["TRAVIS"] == "true"
4
+ require "simplecov"
5
+ require "coveralls"
6
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
7
+ SimpleCov.start do
8
+ add_filter "/test/"
9
+ end
10
+ end
5
11
 
6
12
  ENV["MT_HELL"] = "1" # Forces tests to have at least one assertion to pass.
7
13
 
8
14
  require "minitest/autorun"
9
- require "minitest/parallel_fork"
10
- require "minitest/pride"
15
+
16
+ # Runs tests in parallel. Also, in combination with the MT_HELL environment var
17
+ # set above and the loading of the `minitest-proveit` gem, requires that tests
18
+ # have at least one assertion to pass.
11
19
  require "minitest/hell"
20
+
21
+ require "minitest/pride"
12
22
  require "open3"
13
23
  require "securerandom"
14
24
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: friends
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.29'
4
+ version: '0.30'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Evelyn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-18 00:00:00.000000000 Z
11
+ date: 2017-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chronic
@@ -95,19 +95,19 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '1.6'
97
97
  - !ruby/object:Gem::Dependency
98
- name: codeclimate-test-reporter
98
+ name: coveralls
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0.5'
103
+ version: '0.8'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0.5'
110
+ version: '0.8'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: minitest
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -122,20 +122,6 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '5.5'
125
- - !ruby/object:Gem::Dependency
126
- name: minitest-parallel_fork
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '1.0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '1.0'
139
125
  - !ruby/object:Gem::Dependency
140
126
  name: minitest-proveit
141
127
  requirement: !ruby/object:Gem::Requirement
@@ -151,47 +137,47 @@ dependencies:
151
137
  - !ruby/object:Gem::Version
152
138
  version: '1.0'
153
139
  - !ruby/object:Gem::Dependency
154
- name: overcommit
140
+ name: rake
155
141
  requirement: !ruby/object:Gem::Requirement
156
142
  requirements:
157
143
  - - "~>"
158
144
  - !ruby/object:Gem::Version
159
- version: '0.34'
145
+ version: '11.2'
160
146
  type: :development
161
147
  prerelease: false
162
148
  version_requirements: !ruby/object:Gem::Requirement
163
149
  requirements:
164
150
  - - "~>"
165
151
  - !ruby/object:Gem::Version
166
- version: '0.34'
152
+ version: '11.2'
167
153
  - !ruby/object:Gem::Dependency
168
- name: rake
154
+ name: rubocop
169
155
  requirement: !ruby/object:Gem::Requirement
170
156
  requirements:
171
157
  - - "~>"
172
158
  - !ruby/object:Gem::Version
173
- version: '11.2'
159
+ version: '0.49'
174
160
  type: :development
175
161
  prerelease: false
176
162
  version_requirements: !ruby/object:Gem::Requirement
177
163
  requirements:
178
164
  - - "~>"
179
165
  - !ruby/object:Gem::Version
180
- version: '11.2'
166
+ version: '0.49'
181
167
  - !ruby/object:Gem::Dependency
182
- name: rubocop
168
+ name: simplecov
183
169
  requirement: !ruby/object:Gem::Requirement
184
170
  requirements:
185
171
  - - "~>"
186
172
  - !ruby/object:Gem::Version
187
- version: '0.40'
173
+ version: '0.14'
188
174
  type: :development
189
175
  prerelease: false
190
176
  version_requirements: !ruby/object:Gem::Requirement
191
177
  requirements:
192
178
  - - "~>"
193
179
  - !ruby/object:Gem::Version
194
- version: '0.40'
180
+ version: '0.14'
195
181
  description: Spend time with the people you care about. Introvert-tested. Extrovert-approved.
196
182
  email:
197
183
  - jacobevelyn@gmail.com
@@ -203,7 +189,6 @@ files:
203
189
  - ".gitignore"
204
190
  - ".overcommit.yml"
205
191
  - ".rubocop.yml"
206
- - ".ruby-version"
207
192
  - ".travis.yml"
208
193
  - CHANGELOG.md
209
194
  - CODE_OF_CONDUCT.md
@@ -1 +0,0 @@
1
- 2.4.0