friends 0.51 → 0.55

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Friends
4
- VERSION = "0.51"
4
+ VERSION = "0.55"
5
5
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./test/helper"
4
+
5
+ clean_describe "add alias" do
6
+ subject { run_cmd("add alias #{location_name} #{nickname}") }
7
+
8
+ let(:content) { CONTENT }
9
+
10
+ describe "when location name and alias are blank" do
11
+ let(:location_name) { nil }
12
+ let(:nickname) { nil }
13
+
14
+ it "prints an error message" do
15
+ stderr_only 'Error: Expected "[Location Name]" "[Alias]"'
16
+ end
17
+ end
18
+
19
+ describe "when location name has no matches" do
20
+ let(:location_name) { "Garbage" }
21
+ let(:nickname) { "Big Apple Pie" }
22
+
23
+ it "prints an error message" do
24
+ stderr_only 'Error: No location found for "Garbage"'
25
+ end
26
+ end
27
+
28
+ describe "when location alias has more than one match" do
29
+ let(:location_name) { "'New York City'" }
30
+ let(:nickname) { "'Big Apple'" }
31
+ before do
32
+ run_cmd("add location Manhattan")
33
+ run_cmd("add alias Manhattan 'Big Apple'")
34
+ end
35
+
36
+ it "prints an error message" do
37
+ stderr_only "Error: The location alias "\
38
+ '"Big Apple" is already taken by "Manhattan (a.k.a. Big Apple)"'
39
+ end
40
+ end
41
+
42
+ describe "when location name has one match" do
43
+ let(:location_name) { "'New York City'" }
44
+
45
+ describe "when alias is blank" do
46
+ let(:nickname) { "' '" }
47
+
48
+ it "prints an error message" do
49
+ stderr_only "Error: Alias cannot be blank"
50
+ end
51
+ end
52
+
53
+ describe "when alias is nil" do
54
+ let(:nickname) { nil }
55
+
56
+ it "prints an error message" do
57
+ stderr_only "Error: Alias cannot be blank"
58
+ end
59
+ end
60
+
61
+ describe "when alias is not blank" do
62
+ let(:nickname) { "'Big Apple'" }
63
+
64
+ it "adds alias to location" do
65
+ line_changed "- New York City (a.k.a. NYC a.k.a. NY)",
66
+ "- New York City (a.k.a. NYC a.k.a. NY a.k.a. Big Apple)"
67
+ end
68
+
69
+ it "prints an output message" do
70
+ stdout_only 'Alias added: "New York City (a.k.a. NYC a.k.a. NY a.k.a. Big Apple)"'
71
+ end
72
+ end
73
+ end
74
+ end
@@ -7,6 +7,15 @@ clean_describe "add nickname" do
7
7
 
8
8
  let(:content) { CONTENT }
9
9
 
10
+ describe "when friend name and nickname are blank" do
11
+ let(:friend_name) { nil }
12
+ let(:nickname) { nil }
13
+
14
+ it "prints an error message" do
15
+ stderr_only 'Error: Expected "[Friend Name]" "[Nickname]"'
16
+ end
17
+ end
18
+
10
19
  describe "when friend name has no matches" do
11
20
  let(:friend_name) { "Garbage" }
12
21
  let(:nickname) { "Georgie" }
@@ -7,6 +7,15 @@ clean_describe "add tag" do
7
7
 
8
8
  let(:content) { CONTENT }
9
9
 
10
+ describe "when friend name and tag are blank" do
11
+ let(:friend_name) { nil }
12
+ let(:tag) { nil }
13
+
14
+ it "prints an error message" do
15
+ stderr_only 'Error: Expected "[Friend Name]" "[Tag]"'
16
+ end
17
+ end
18
+
10
19
  describe "when friend name has no matches" do
11
20
  let(:friend_name) { "Garbage" }
12
21
  let(:tag) { "school" }
@@ -134,6 +134,7 @@ Not cleaning file: "#{filename}" ("exit 1 #" did not exit successfully)
134
134
  - Atlantis
135
135
  - Martha's Vineyard
136
136
  - Mysterious Mountains
137
+ - New York City (a.k.a. NYC a.k.a. NY)
137
138
  - Paris
138
139
  EXPECTED_CONTENT
139
140
  end
@@ -26,26 +26,26 @@ clean_describe "list friends" do
26
26
  # only reads from the (usually-sorted) file.
27
27
  let(:content) { SCRAMBLED_CONTENT }
28
28
 
29
- it "lists friends in file order" do
29
+ it "lists friends in alphabetical order" do
30
30
  stdout_only <<-OUTPUT
31
31
  George Washington Carver
32
- Marie Curie
33
32
  Grace Hopper
34
- Stanislav Petrov
33
+ Marie Curie
35
34
  Norman Borlaug
35
+ Stanislav Petrov
36
36
  OUTPUT
37
37
  end
38
38
 
39
39
  describe "--verbose" do
40
40
  subject { run_cmd("list friends --verbose") }
41
41
 
42
- it "lists friends in file order with details" do
42
+ it "lists friends in sorted order with details" do
43
43
  stdout_only <<-OUTPUT
44
44
  George Washington Carver
45
- Marie Curie [Atlantis] @science
46
45
  Grace Hopper (a.k.a. The Admiral a.k.a. Amazing Grace) [Paris] @navy @science
47
- Stanislav Petrov (a.k.a. Stan) @doesnt-trust-computers @doesnt-trust-computers:military-uses
46
+ Marie Curie [Atlantis] @science
48
47
  Norman Borlaug (a.k.a. Norm) @science @science:outdoors @science:outdoors:agronomy
48
+ Stanislav Petrov (a.k.a. Stan) @doesnt-trust-computers @doesnt-trust-computers:military-uses
49
49
  OUTPUT
50
50
  end
51
51
  end
@@ -73,8 +73,8 @@ Norman Borlaug (a.k.a. Norm) @science @science:outdoors @science:outdoors:agrono
73
73
 
74
74
  it "matches tag case-insensitively" do
75
75
  stdout_only <<-OUTPUT
76
- Marie Curie
77
76
  Grace Hopper
77
+ Marie Curie
78
78
  Norman Borlaug
79
79
  OUTPUT
80
80
  end
@@ -114,5 +114,99 @@ Stanislav Petrov
114
114
  end
115
115
  end
116
116
  end
117
+
118
+ describe "--sort" do
119
+ subject { run_cmd("list friends --sort #{sort} #{reverse}") }
120
+
121
+ let(:reverse) { nil }
122
+
123
+ # Use scrambled content to differentiate between output that is sorted and output that
124
+ # only reads from the (usually-sorted) file.
125
+ let(:content) { SCRAMBLED_CONTENT }
126
+
127
+ describe "alphabetical" do
128
+ let(:sort) { "alphabetical" }
129
+
130
+ it "lists friends in sorted order" do
131
+ stdout_only <<-OUTPUT
132
+ George Washington Carver
133
+ Grace Hopper
134
+ Marie Curie
135
+ Norman Borlaug
136
+ Stanislav Petrov
137
+ OUTPUT
138
+ end
139
+
140
+ describe "--reverse" do
141
+ let(:reverse) { "--reverse" }
142
+
143
+ it "lists friends in reverse order" do
144
+ stdout_only <<-OUTPUT
145
+ Stanislav Petrov
146
+ Norman Borlaug
147
+ Marie Curie
148
+ Grace Hopper
149
+ George Washington Carver
150
+ OUTPUT
151
+ end
152
+ end
153
+ end
154
+
155
+ describe "n-activities" do
156
+ let(:sort) { "n-activities" }
157
+
158
+ it "lists friends in sorted order" do
159
+ stdout_only <<-OUTPUT
160
+ 3 activities: George Washington Carver
161
+ 2 activities: Grace Hopper
162
+ 1 activity: Marie Curie
163
+ 1 activity: Norman Borlaug
164
+ 0 activities: Stanislav Petrov
165
+ OUTPUT
166
+ end
167
+
168
+ describe "--reverse" do
169
+ let(:reverse) { "--reverse" }
170
+
171
+ it "lists friends in reverse order" do
172
+ stdout_only <<-OUTPUT
173
+ 0 activities: Stanislav Petrov
174
+ 1 activity: Norman Borlaug
175
+ 1 activity: Marie Curie
176
+ 2 activities: Grace Hopper
177
+ 3 activities: George Washington Carver
178
+ OUTPUT
179
+ end
180
+ end
181
+ end
182
+
183
+ describe "recency" do
184
+ let(:sort) { "recency" }
185
+
186
+ it "lists friends in sorted order" do
187
+ stdout_only_regexes [
188
+ "N/A days ago: Stanislav Petrov",
189
+ /\d+ days ago: George Washington Carver/,
190
+ /\d+ days ago: Norman Borlaug/,
191
+ /\d+ days ago: Grace Hopper/,
192
+ /\d+ days ago: Marie Curie/
193
+ ]
194
+ end
195
+
196
+ describe "--reverse" do
197
+ let(:reverse) { "--reverse" }
198
+
199
+ it "lists friends in reverse order" do
200
+ stdout_only_regexes [
201
+ /\d+ days ago: Marie Curie/,
202
+ /\d+ days ago: Grace Hopper/,
203
+ /\d+ days ago: Norman Borlaug/,
204
+ /\d+ days ago: George Washington Carver/,
205
+ "N/A days ago: Stanislav Petrov"
206
+ ]
207
+ end
208
+ end
209
+ end
210
+ end
117
211
  end
118
212
  end
@@ -26,12 +26,114 @@ clean_describe "list locations" do
26
26
  # only reads from the (usually-sorted) file.
27
27
  let(:content) { SCRAMBLED_CONTENT }
28
28
 
29
- it "lists locations in file order" do
29
+ it "lists locations in alphabetical" do
30
30
  stdout_only <<-OUTPUT
31
- Paris
32
31
  Atlantis
33
32
  Martha's Vineyard
33
+ New York City
34
+ Paris
34
35
  OUTPUT
35
36
  end
37
+
38
+ describe "--sort" do
39
+ subject { run_cmd("list locations --sort #{sort} #{reverse}") }
40
+
41
+ let(:reverse) { nil }
42
+
43
+ # Use scrambled content to differentiate between output that is sorted and output that
44
+ # only reads from the (usually-sorted) file.
45
+ let(:content) { SCRAMBLED_CONTENT }
46
+
47
+ describe "alphabetical" do
48
+ let(:sort) { "alphabetical" }
49
+
50
+ it "lists locations in sorted order" do
51
+ stdout_only <<-OUTPUT
52
+ Atlantis
53
+ Martha's Vineyard
54
+ New York City
55
+ Paris
56
+ OUTPUT
57
+ end
58
+
59
+ describe "--reverse" do
60
+ let(:reverse) { "--reverse" }
61
+
62
+ it "lists locations in reverse order" do
63
+ stdout_only <<-OUTPUT
64
+ Paris
65
+ New York City
66
+ Martha's Vineyard
67
+ Atlantis
68
+ OUTPUT
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "n-activities" do
74
+ let(:sort) { "n-activities" }
75
+
76
+ it "lists locations in sorted order" do
77
+ stdout_only <<-OUTPUT
78
+ 1 activity: Paris
79
+ 1 activity: Atlantis
80
+ 1 activity: Martha's Vineyard
81
+ 0 activities: New York City
82
+ OUTPUT
83
+ end
84
+
85
+ describe "--reverse" do
86
+ let(:reverse) { "--reverse" }
87
+
88
+ it "lists locations in reverse order" do
89
+ stdout_only <<-OUTPUT
90
+ 0 activities: New York City
91
+ 1 activity: Martha's Vineyard
92
+ 1 activity: Atlantis
93
+ 1 activity: Paris
94
+ OUTPUT
95
+ end
96
+ end
97
+ end
98
+
99
+ describe "recency" do
100
+ let(:sort) { "recency" }
101
+
102
+ it "lists locations in sorted order" do
103
+ stdout_only_regexes [
104
+ "N/A days ago: New York City",
105
+ /\d+ days ago: Atlantis/,
106
+ /\d+ days ago: Martha's Vineyard/,
107
+ /\d+ days ago: Paris/
108
+ ]
109
+ end
110
+
111
+ describe "--reverse" do
112
+ let(:reverse) { "--reverse" }
113
+
114
+ it "lists locations in reverse order" do
115
+ stdout_only_regexes [
116
+ /\d+ days ago: Paris/,
117
+ /\d+ days ago: Martha's Vineyard/,
118
+ /\d+ days ago: Atlantis/,
119
+ "N/A days ago: New York City"
120
+ ]
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "--verbose" do
127
+ subject { run_cmd("list locations --verbose") }
128
+
129
+ it "lists locations in alphabetical order with details" do
130
+ stdout_only <<-OUTPUT
131
+ Atlantis
132
+ Martha's Vineyard
133
+ New York City (a.k.a. NYC a.k.a. NY)
134
+ Paris
135
+ OUTPUT
136
+ end
137
+ end
36
138
  end
37
139
  end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./test/helper"
4
+
5
+ clean_describe "remove alias" do
6
+ subject { run_cmd("remove alias #{location_name} #{nickname}") }
7
+
8
+ let(:content) { CONTENT }
9
+
10
+ describe "when location and nickname are nil" do
11
+ let(:location_name) { nil }
12
+ let(:nickname) { nil }
13
+
14
+ it "prints an error message" do
15
+ stderr_only 'Error: Expected "[Location Name]" "[Alias]"'
16
+ end
17
+ end
18
+
19
+ describe "when location name has no matches" do
20
+ let(:location_name) { "Garbage" }
21
+ let(:nickname) { "'Big Apple Pie'" }
22
+
23
+ it "prints an error message" do
24
+ stderr_only 'Error: No location found for "Garbage"'
25
+ end
26
+ end
27
+
28
+ describe "when location name has one match" do
29
+ let(:location_name) { "'New York City'" }
30
+
31
+ describe "when alias is nil" do
32
+ let(:nickname) { nil }
33
+ it "prints an error message" do
34
+ stderr_only "Error: Alias cannot be blank"
35
+ end
36
+ end
37
+
38
+ describe "when alias is not present on location" do
39
+ let(:nickname) { "Gotham" }
40
+ it "prints an error message" do
41
+ stderr_only 'Error: Alias "Gotham" not found for "New York City"'
42
+ end
43
+ end
44
+
45
+ describe "when alias is present on location" do
46
+ let(:nickname) { "'NYC'" }
47
+
48
+ it "removes alias from location" do
49
+ line_changed(
50
+ "- New York City (a.k.a. NYC a.k.a. NY)",
51
+ "- New York City (a.k.a. NY)"
52
+ )
53
+ end
54
+
55
+ it "removes parenthetical from file when location has no more nicknames" do
56
+ run_cmd("remove alias #{location_name} 'NY'")
57
+ line_changed(
58
+ "- New York City (a.k.a. NYC)",
59
+ "- New York City"
60
+ )
61
+ end
62
+
63
+ it "prints an output message" do
64
+ stdout_only 'Alias removed: "New York City (a.k.a. NY)"'
65
+ end
66
+ end
67
+ end
68
+ end