friends 0.29 → 0.30
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/.gitignore +1 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +2 -5
- data/CHANGELOG.md +15 -0
- data/PULL_REQUEST_TEMPLATE.md +2 -2
- data/README.md +41 -6
- data/bin/friends +7 -0
- data/friends.gemspec +3 -4
- data/lib/friends/commands/graph.rb +4 -2
- data/lib/friends/commands/list.rb +8 -27
- data/lib/friends/graph.rb +1 -0
- data/lib/friends/introvert.rb +67 -30
- data/lib/friends/serializable.rb +1 -1
- data/lib/friends/version.rb +1 -1
- data/test/commands/graph_spec.rb +34 -0
- data/test/commands/list/activities_spec.rb +36 -0
- data/test/commands/list/favorite/friends_spec.rb +84 -2
- data/test/commands/list/favorite/locations_spec.rb +88 -1
- data/test/commands/list/friends_spec.rb +25 -0
- data/test/helper.rb +14 -4
- metadata +14 -29
- data/.ruby-version +0 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 81e378aa8d3e1a7285adcb3f92cc91977c22eca2
         | 
| 4 | 
            +
              data.tar.gz: f48b3ccd7d4006679c7b072b06a980432c759a6c
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ee11daf225f5c245b68a732267b0fafd7041d478d8cff7d68860f9b50a71f9a3db51de2edd4a7dac723a6db5c5c26045a697a21bc7215acc770bed3a2390ee10
         | 
| 7 | 
            +
              data.tar.gz: e47d850e7cc62ea74a0c212f0315de2cc5bd1eb72f331526ccee67dd39d7599b091a546770d14ba2af7132f929ab8d9076f61b28cb8a68a36432ccda3d481f56
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.rubocop.yml
    CHANGED
    
    | @@ -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 |  | 
    
        data/.travis.yml
    CHANGED
    
    | @@ -5,10 +5,7 @@ rvm: | |
| 5 5 | 
             
            - 2.3.0
         | 
| 6 6 | 
             
            - 2.4.0
         | 
| 7 7 | 
             
            script:
         | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 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
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -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 |  | 
    
        data/PULL_REQUEST_TEMPLATE.md
    CHANGED
    
    | @@ -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  | 
| 10 | 
            -
            - [ ] Rubocop reports no issues on  | 
| 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 | 
             
            [](https://badge.fury.io/rb/friends) [](https://gemnasium.com/github.com/JacobEvelyn/friends)
         | 
| 2 | 
            -
             [](https://coveralls.io/github/JacobEvelyn/friends) [](https://travis-ci.org/JacobEvelyn/friends) [](http://inch-ci.org/github/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  | 
| 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  | 
| 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              ( | 
| 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   ( | 
| 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:
         | 
    
        data/bin/friends
    CHANGED
    
    | @@ -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"
         | 
    
        data/friends.gemspec
    CHANGED
    
    | @@ -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 " | 
| 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. | 
| 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 | 
            -
                     | 
| 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 | 
            -
                     | 
| 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
         | 
    
        data/lib/friends/graph.rb
    CHANGED
    
    
    
        data/lib/friends/introvert.rb
    CHANGED
    
    | @@ -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  | 
| 190 | 
            -
                #    | 
| 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  | 
| 204 | 
            -
                   | 
| 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  | 
| 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  | 
| 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  | 
| 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 | 
| 457 | 
            -
                #   for unfiltered
         | 
| 458 | 
            -
                # @param tagged [String] the  | 
| 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. | 
| 470 | 
            -
                     | 
| 471 | 
            -
                    acts = acts.select  | 
| 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 | 
            -
                   | 
| 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 | 
            -
                   | 
| 508 | 
            -
             | 
| 509 | 
            -
                     | 
| 510 | 
            -
             | 
| 511 | 
            -
             | 
| 512 | 
            -
             | 
| 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 |  | 
    
        data/lib/friends/serializable.rb
    CHANGED
    
    
    
        data/lib/friends/version.rb
    CHANGED
    
    
    
        data/test/commands/graph_spec.rb
    CHANGED
    
    | @@ -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 | 
            -
             | 
| 61 | 
            -
             | 
| 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 | 
            -
             | 
| 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
         | 
    
        data/test/helper.rb
    CHANGED
    
    | @@ -1,14 +1,24 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 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 | 
            -
             | 
| 10 | 
            -
             | 
| 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. | 
| 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- | 
| 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:  | 
| 98 | 
            +
              name: coveralls
         | 
| 99 99 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 100 100 | 
             
                requirements:
         | 
| 101 101 | 
             
                - - "~>"
         | 
| 102 102 | 
             
                  - !ruby/object:Gem::Version
         | 
| 103 | 
            -
                    version: '0. | 
| 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. | 
| 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:  | 
| 140 | 
            +
              name: rake
         | 
| 155 141 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 156 142 | 
             
                requirements:
         | 
| 157 143 | 
             
                - - "~>"
         | 
| 158 144 | 
             
                  - !ruby/object:Gem::Version
         | 
| 159 | 
            -
                    version: ' | 
| 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: ' | 
| 152 | 
            +
                    version: '11.2'
         | 
| 167 153 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 168 | 
            -
              name:  | 
| 154 | 
            +
              name: rubocop
         | 
| 169 155 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 170 156 | 
             
                requirements:
         | 
| 171 157 | 
             
                - - "~>"
         | 
| 172 158 | 
             
                  - !ruby/object:Gem::Version
         | 
| 173 | 
            -
                    version: ' | 
| 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: ' | 
| 166 | 
            +
                    version: '0.49'
         | 
| 181 167 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 182 | 
            -
              name:  | 
| 168 | 
            +
              name: simplecov
         | 
| 183 169 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 184 170 | 
             
                requirements:
         | 
| 185 171 | 
             
                - - "~>"
         | 
| 186 172 | 
             
                  - !ruby/object:Gem::Version
         | 
| 187 | 
            -
                    version: '0. | 
| 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. | 
| 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
         | 
    
        data/.ruby-version
    DELETED
    
    | @@ -1 +0,0 @@ | |
| 1 | 
            -
            2.4.0
         |