friends 0.28 → 0.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -4
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +2 -0
  5. data/CHANGELOG.md +13 -0
  6. data/README.md +35 -5
  7. data/Rakefile +1 -1
  8. data/bin/friends +7 -379
  9. data/friends.gemspec +3 -1
  10. data/lib/friends/activity.rb +4 -4
  11. data/lib/friends/commands/add.rb +64 -0
  12. data/lib/friends/commands/clean.rb +9 -0
  13. data/lib/friends/commands/edit.rb +12 -0
  14. data/lib/friends/commands/graph.rb +56 -0
  15. data/lib/friends/commands/list.rb +143 -0
  16. data/lib/friends/commands/remove.rb +27 -0
  17. data/lib/friends/commands/rename.rb +30 -0
  18. data/lib/friends/commands/set.rb +14 -0
  19. data/lib/friends/commands/stats.rb +11 -0
  20. data/lib/friends/commands/suggest.rb +20 -0
  21. data/lib/friends/commands/update.rb +29 -0
  22. data/lib/friends/graph.rb +7 -7
  23. data/lib/friends/introvert.rb +23 -18
  24. data/lib/friends/version.rb +1 -1
  25. data/test/commands/add/activity_spec.rb +379 -0
  26. data/test/commands/add/friend_spec.rb +30 -0
  27. data/test/commands/add/location_spec.rb +30 -0
  28. data/test/commands/add/nickname_spec.rb +50 -0
  29. data/test/commands/add/tag_spec.rb +65 -0
  30. data/test/commands/clean_spec.rb +39 -0
  31. data/test/commands/graph_spec.rb +147 -0
  32. data/test/commands/help_spec.rb +45 -0
  33. data/test/commands/list/activities_spec.rb +136 -0
  34. data/test/commands/list/favorite/friends_spec.rb +77 -0
  35. data/test/commands/list/favorite/locations_spec.rb +82 -0
  36. data/test/commands/list/friends_spec.rb +76 -0
  37. data/test/commands/list/locations_spec.rb +35 -0
  38. data/test/commands/list/tags_spec.rb +58 -0
  39. data/test/commands/remove/nickname_spec.rb +63 -0
  40. data/test/commands/remove/tag_spec.rb +64 -0
  41. data/test/commands/rename/friend_spec.rb +55 -0
  42. data/test/commands/rename/location_spec.rb +43 -0
  43. data/test/commands/set/location_spec.rb +54 -0
  44. data/test/commands/stats_spec.rb +41 -0
  45. data/test/commands/suggest_spec.rb +86 -0
  46. data/test/commands/update_spec.rb +13 -0
  47. data/test/helper.rb +114 -0
  48. metadata +89 -15
  49. data/test/activity_spec.rb +0 -597
  50. data/test/friend_spec.rb +0 -241
  51. data/test/graph_spec.rb +0 -92
  52. data/test/introvert_spec.rb +0 -969
  53. data/test/location_spec.rb +0 -60
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./test/helper"
4
+
5
+ clean_describe "list favorite friends" do
6
+ subject { run_cmd("list favorite friends") }
7
+
8
+ describe "when file does not exist" do
9
+ it "prints a no-data message" do
10
+ stdout_only "Your favorite friends:"
11
+ end
12
+ end
13
+
14
+ describe "when file is empty" do
15
+ let(:content) { "" }
16
+
17
+ it "prints a no-data message" do
18
+ stdout_only "Your favorite friends:"
19
+ end
20
+ end
21
+
22
+ describe "when file has content" do
23
+ let(:content) do
24
+ <<-FILE
25
+ ### Activities:
26
+ - 2017-01-01: Did some math with **Grace Hopper**.
27
+ - 2015-11-01: **Grace Hopper** and I went to _Marie's Diner_. George had to cancel at the last minute. @food
28
+ - 2015-01-04: Got lunch with **Grace Hopper** and **George Washington Carver**. @food
29
+ - 2014-12-31: Celebrated the new year in _Paris_ with **Marie Curie**. @partying
30
+ - 2014-11-15: Talked to **George Washington Carver** on the phone for an hour.
31
+
32
+ ### Friends:
33
+ - George Washington Carver
34
+ - Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
35
+ - Marie Curie [Atlantis] @science
36
+ FILE
37
+ end
38
+
39
+ it "lists friends in order of decreasing activity" do
40
+ stdout_only <<-OUTPUT
41
+ Your favorite friends:
42
+ 1. Grace Hopper (3 activities)
43
+ 2. George Washington Carver (2)
44
+ 3. Marie Curie (1)
45
+ OUTPUT
46
+ end
47
+
48
+ describe "--limit" do
49
+ subject { run_cmd("list favorite friends --limit #{limit}") }
50
+
51
+ describe "when limit is less than 1" do
52
+ let(:limit) { 0 }
53
+ it "prints an error message" do
54
+ stderr_only "Error: Favorites limit must be positive"
55
+ end
56
+ end
57
+
58
+ describe "when limit is 1" do
59
+ let(:limit) { 1 }
60
+ it "outputs as a best friend" do
61
+ stdout_only "Your best friend is Grace Hopper (3 activities)"
62
+ end
63
+ end
64
+
65
+ describe "when limit is greater than 1" do
66
+ let(:limit) { 2 }
67
+ it "limits output to the number specified" do
68
+ stdout_only <<-OUTPUT
69
+ Your favorite friends:
70
+ 1. Grace Hopper (3 activities)
71
+ 2. George Washington Carver (2)
72
+ OUTPUT
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./test/helper"
4
+
5
+ clean_describe "list favorite locations" do
6
+ subject { run_cmd("list favorite locations") }
7
+
8
+ describe "when file does not exist" do
9
+ it "prints a no-data message" do
10
+ stdout_only "Your favorite locations:"
11
+ end
12
+ end
13
+
14
+ describe "when file is empty" do
15
+ let(:content) { "" }
16
+
17
+ it "prints a no-data message" do
18
+ stdout_only "Your favorite locations:"
19
+ end
20
+ end
21
+
22
+ describe "when file has content" do
23
+ let(:content) do
24
+ <<-FILE
25
+ ### Activities:
26
+ - 2017-01-01: **Grace Hopper** and I went to _Marie's Diner_ for breakfast.
27
+ - 2015-11-01: **Grace Hopper** and I went to _Marie's Diner_. George had to cancel at the last minute. @food
28
+ - 2015-01-04: Got lunch with **Grace Hopper** and **George Washington Carver**. @food
29
+ - 2014-12-31: Celebrated the new year in _Paris_ with **Marie Curie**. @partying
30
+ - 2014-11-15: Talked to **George Washington Carver** on the phone for an hour.
31
+
32
+ ### Friends:
33
+ - George Washington Carver
34
+ - Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
35
+ - Marie Curie [Atlantis] @science
36
+
37
+ ### Locations:
38
+ - Atlantis
39
+ - Marie's Diner
40
+ - Paris
41
+ FILE
42
+ end
43
+
44
+ it "lists locations in order of decreasing activity" do
45
+ stdout_only <<-OUTPUT
46
+ Your favorite locations:
47
+ 1. Marie's Diner (2 activities)
48
+ 2. Paris (1)
49
+ 3. Atlantis (0)
50
+ OUTPUT
51
+ end
52
+
53
+ describe "--limit" do
54
+ subject { run_cmd("list favorite locations --limit #{limit}") }
55
+
56
+ describe "when limit is less than 1" do
57
+ let(:limit) { 0 }
58
+ it "prints an error message" do
59
+ stderr_only "Error: Favorites limit must be positive"
60
+ end
61
+ end
62
+
63
+ describe "when limit is 1" do
64
+ let(:limit) { 1 }
65
+ it "outputs as a favorite location" do
66
+ stdout_only "Your favorite location is Marie's Diner (2 activities)"
67
+ end
68
+ end
69
+
70
+ describe "when limit is greater than 1" do
71
+ let(:limit) { 2 }
72
+ it "limits output to the number specified" do
73
+ stdout_only <<-OUTPUT
74
+ Your favorite locations:
75
+ 1. Marie's Diner (2 activities)
76
+ 2. Paris (1)
77
+ OUTPUT
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./test/helper"
4
+
5
+ clean_describe "list friends" do
6
+ subject { run_cmd("list friends") }
7
+
8
+ describe "when file does not exist" do
9
+ it "does not list anything" do
10
+ stdout_only ""
11
+ end
12
+ end
13
+
14
+ describe "when file is empty" do
15
+ let(:content) { "" }
16
+
17
+ it "does not list anything" do
18
+ stdout_only ""
19
+ end
20
+ end
21
+
22
+ describe "when file has content" do
23
+ # Use scrambled content to differentiate between output that is sorted and output that
24
+ # only reads from the (usually-sorted) file.
25
+ let(:content) { SCRAMBLED_CONTENT }
26
+
27
+ it "lists friends in file order" do
28
+ stdout_only <<-OUTPUT
29
+ George Washington Carver
30
+ Marie Curie
31
+ Grace Hopper
32
+ OUTPUT
33
+ end
34
+
35
+ describe "--verbose" do
36
+ subject { run_cmd("list friends --verbose") }
37
+
38
+ it "lists friends in file order with details" do
39
+ stdout_only <<-OUTPUT
40
+ George Washington Carver
41
+ Marie Curie [Atlantis] @science
42
+ Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
43
+ OUTPUT
44
+ end
45
+ end
46
+
47
+ describe "--in" do
48
+ subject { run_cmd("list friends --in #{location_name}") }
49
+
50
+ describe "when location does not exist" do
51
+ let(:location_name) { "Garbage" }
52
+ it "prints an error message" do
53
+ stderr_only 'Error: No location found for "Garbage"'
54
+ end
55
+ end
56
+
57
+ describe "when location exists" do
58
+ let(:location_name) { "paris" }
59
+ it "matches location case-insensitively" do
60
+ stdout_only "Grace Hopper"
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "--tagged" do
66
+ subject { run_cmd("list friends --tagged science") }
67
+
68
+ it "matches tag case-sensitively" do
69
+ stdout_only <<-OUTPUT
70
+ Marie Curie
71
+ Grace Hopper
72
+ OUTPUT
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./test/helper"
4
+
5
+ clean_describe "list locations" do
6
+ subject { run_cmd("list locations") }
7
+
8
+ describe "when file does not exist" do
9
+ it "does not list anything" do
10
+ stdout_only ""
11
+ end
12
+ end
13
+
14
+ describe "when file is empty" do
15
+ let(:content) { "" }
16
+
17
+ it "does not list anything" do
18
+ stdout_only ""
19
+ end
20
+ end
21
+
22
+ describe "when file has content" do
23
+ # Use scrambled content to differentiate between output that is sorted and output that
24
+ # only reads from the (usually-sorted) file.
25
+ let(:content) { SCRAMBLED_CONTENT }
26
+
27
+ it "lists locations in file order" do
28
+ stdout_only <<-OUTPUT
29
+ Paris
30
+ Atlantis
31
+ Marie's Diner
32
+ OUTPUT
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./test/helper"
4
+
5
+ clean_describe "list tags" do
6
+ subject { run_cmd("list tags") }
7
+
8
+ describe "when file does not exist" do
9
+ it "does not list anything" do
10
+ stdout_only ""
11
+ end
12
+ end
13
+
14
+ describe "when file is empty" do
15
+ let(:content) { "" }
16
+
17
+ it "does not list anything" do
18
+ stdout_only ""
19
+ end
20
+ end
21
+
22
+ describe "when file has content" do
23
+ # Use scrambled content to differentiate between output that is sorted and output that
24
+ # only reads from the (usually-sorted) file.
25
+ let(:content) { SCRAMBLED_CONTENT }
26
+
27
+ it "lists unique tags" do
28
+ stdout_only <<-OUTPUT
29
+ @food
30
+ @navy
31
+ @partying
32
+ @science
33
+ OUTPUT
34
+ end
35
+
36
+ describe "--from activities" do
37
+ subject { run_cmd("list tags --from activities") }
38
+
39
+ it "lists unique tags from activities" do
40
+ stdout_only <<-OUTPUT
41
+ @food
42
+ @partying
43
+ OUTPUT
44
+ end
45
+ end
46
+
47
+ describe "--from friends" do
48
+ subject { run_cmd("list tags --from friends") }
49
+
50
+ it "lists unique tags from friends" do
51
+ stdout_only <<-OUTPUT
52
+ @navy
53
+ @science
54
+ OUTPUT
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./test/helper"
4
+
5
+ clean_describe "remove nickname" do
6
+ subject { run_cmd("remove nickname #{friend_name} #{nickname}") }
7
+
8
+ let(:content) { CONTENT }
9
+
10
+ describe "when friend name has no matches" do
11
+ let(:friend_name) { "Garbage" }
12
+ let(:nickname) { "'Amazing Grace'" }
13
+
14
+ it "prints an error message" do
15
+ stderr_only 'Error: No friend found for "Garbage"'
16
+ end
17
+ end
18
+
19
+ describe "when friend name has more than one match" do
20
+ let(:friend_name) { "George" }
21
+ let(:nickname) { "'Amazing Grace'" }
22
+ before { run_cmd("add friend George Harrison") }
23
+
24
+ it "prints an error message" do
25
+ stderr_only 'Error: More than one friend found for "George": '\
26
+ "George Harrison, George Washington Carver"
27
+ end
28
+ end
29
+
30
+ describe "when friend name has one match" do
31
+ let(:friend_name) { "Grace" }
32
+
33
+ describe "when nickname is not present on friend" do
34
+ let(:nickname) { "Gracie" }
35
+ it "prints an error message" do
36
+ stderr_only 'Error: Nickname "Gracie" not found for "Grace Hopper"'
37
+ end
38
+ end
39
+
40
+ describe "when nickname is present on friend" do
41
+ let(:nickname) { "'Amazing Grace'" }
42
+
43
+ it "removes nickname from friend" do
44
+ line_changed(
45
+ "- Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science",
46
+ "- Grace Hopper (a.k.a. The Admiral) [Paris] @navy @science"
47
+ )
48
+ end
49
+
50
+ it "removes parenthetical from file when friend has no more nicknames" do
51
+ run_cmd("remove nickname #{friend_name} 'The Admiral'")
52
+ line_changed(
53
+ "- Grace Hopper (a.k.a. Amazing Grace) [Paris] @navy @science",
54
+ "- Grace Hopper [Paris] @navy @science"
55
+ )
56
+ end
57
+
58
+ it "prints an output message" do
59
+ stdout_only 'Nickname removed: "Grace Hopper (a.k.a. The Admiral) [Paris] @navy @science"'
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./test/helper"
4
+
5
+ clean_describe "remove tag" do
6
+ subject { run_cmd("remove tag #{friend_name} #{tag}") }
7
+
8
+ let(:content) { CONTENT }
9
+
10
+ describe "when friend name has no matches" do
11
+ let(:friend_name) { "Garbage" }
12
+ let(:tag) { "science" }
13
+
14
+ it "prints an error message" do
15
+ stderr_only 'Error: No friend found for "Garbage"'
16
+ end
17
+ end
18
+
19
+ describe "when friend name has more than one match" do
20
+ let(:friend_name) { "George" }
21
+ let(:tag) { "science" }
22
+ before { run_cmd("add friend George Harrison") }
23
+
24
+ it "prints an error message" do
25
+ stderr_only 'Error: More than one friend found for "George": '\
26
+ "George Harrison, George Washington Carver"
27
+ end
28
+ end
29
+
30
+ describe "when friend name has one match" do
31
+ let(:friend_name) { "Marie" }
32
+
33
+ describe "when tag is not present on friend" do
34
+ let(:tag) { "garbage" }
35
+ it "prints an error message" do
36
+ stderr_only 'Error: Tag "@garbage" not found for "Marie Curie"'
37
+ end
38
+ end
39
+
40
+ describe "when tag is present on friend" do
41
+ let(:tag) { "science" }
42
+
43
+ it "removes tag from friend" do
44
+ line_changed "- Marie Curie [Atlantis] @science", "- Marie Curie [Atlantis]"
45
+ end
46
+
47
+ it "prints an output message" do
48
+ stdout_only 'Tag removed from friend: "Marie Curie [Atlantis]"'
49
+ end
50
+
51
+ describe "when tag is passed with @" do
52
+ let(:tag) { "@science" }
53
+
54
+ it "adds tag to friend" do
55
+ line_changed "- Marie Curie [Atlantis] @science", "- Marie Curie [Atlantis]"
56
+ end
57
+
58
+ it "prints an output message" do
59
+ stdout_only 'Tag removed from friend: "Marie Curie [Atlantis]"'
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end