friends 0.34 → 0.35
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/CHANGELOG.md +21 -0
- data/README.md +79 -20
- data/RELEASING.md +7 -6
- data/friends.md +4 -0
- data/lib/friends/activity.rb +4 -291
- data/lib/friends/commands/add.rb +15 -13
- data/lib/friends/commands/list.rb +51 -47
- data/lib/friends/commands/stats.rb +3 -0
- data/lib/friends/event.rb +298 -0
- data/lib/friends/introvert.rb +109 -57
- data/lib/friends/note.rb +19 -0
- data/lib/friends/version.rb +1 -1
- data/test/add_event_helper.rb +410 -0
- data/test/commands/add/activity_spec.rb +6 -350
- data/test/commands/add/note_spec.rb +55 -0
- data/test/commands/clean_spec.rb +25 -3
- data/test/commands/list/notes_spec.rb +179 -0
- data/test/commands/list/tags_spec.rb +24 -0
- data/test/commands/stats_spec.rb +100 -7
- data/test/helper.rb +12 -0
- metadata +10 -2
|
@@ -3,323 +3,7 @@
|
|
|
3
3
|
require "date"
|
|
4
4
|
|
|
5
5
|
require "./test/helper"
|
|
6
|
-
|
|
7
|
-
def date_parsing_specs(test_stdout: true)
|
|
8
|
-
describe "date parsing" do
|
|
9
|
-
let(:description) { "Test." }
|
|
10
|
-
|
|
11
|
-
describe "when date is in YYYY-MM-DD" do
|
|
12
|
-
let(:date) { "2017-01-01" }
|
|
13
|
-
|
|
14
|
-
it { line_added "- #{date}: #{description}" }
|
|
15
|
-
it { stdout_only "Activity added: \"#{date}: #{description}\"" } if test_stdout
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
describe "when date is in MM-DD-YYYY" do
|
|
19
|
-
let(:date) { "01-02-2017" }
|
|
20
|
-
|
|
21
|
-
it { line_added "- 2017-01-02: #{description}" }
|
|
22
|
-
it { stdout_only "Activity added: \"2017-01-02: #{description}\"" } if test_stdout
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
describe "when date is invalid" do
|
|
26
|
-
let(:date) { "2017-02-30" }
|
|
27
|
-
|
|
28
|
-
it { line_added "- 2017-03-02: #{description}" }
|
|
29
|
-
it { stdout_only "Activity added: \"2017-03-02: #{description}\"" } if test_stdout
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
describe "when date is natural language and in full" do
|
|
33
|
-
let(:date) { "February 23rd, 2017" }
|
|
34
|
-
|
|
35
|
-
it { line_added "- 2017-02-23: #{description}" }
|
|
36
|
-
it { stdout_only "Activity added: \"2017-02-23: #{description}\"" } if test_stdout
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
describe "when date is natural language and only month and day" do
|
|
40
|
-
# We use two days rather than just one to avoid strange behavior around
|
|
41
|
-
# edge cases when the test is being run right around midnight.
|
|
42
|
-
let(:two_days_in_seconds) { 2 * 24 * 60 * 60 }
|
|
43
|
-
let(:raw_date) { Time.now + two_days_in_seconds }
|
|
44
|
-
let(:date) { raw_date.strftime("%B %d") }
|
|
45
|
-
let(:expected_year) { raw_date.strftime("%Y").to_i - 1 }
|
|
46
|
-
let(:expected_date_str) { "#{expected_year}-#{raw_date.strftime('%m-%d')}" }
|
|
47
|
-
|
|
48
|
-
it { line_added "- #{expected_date_str}: #{description}" }
|
|
49
|
-
it { stdout_only "Activity added: \"#{expected_date_str}: #{description}\"" } if test_stdout
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def description_parsing_specs(test_stdout: true)
|
|
55
|
-
describe "description parsing" do
|
|
56
|
-
let(:date) { Date.today.strftime }
|
|
57
|
-
|
|
58
|
-
describe "when description includes a friend's full name (case insensitive)" do
|
|
59
|
-
let(:description) { "Lunch with grace hopper." }
|
|
60
|
-
|
|
61
|
-
it { line_added "- #{date}: Lunch with **Grace Hopper**." }
|
|
62
|
-
it { stdout_only "Activity added: \"#{date}: Lunch with Grace Hopper.\"" } if test_stdout
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
describe "when description includes a friend's first name (case insensitive)" do
|
|
66
|
-
let(:description) { "Lunch with grace." }
|
|
67
|
-
|
|
68
|
-
it { line_added "- #{date}: Lunch with **Grace Hopper**." }
|
|
69
|
-
it { stdout_only "Activity added: \"#{date}: Lunch with Grace Hopper.\"" } if test_stdout
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
describe "when description has a friend's first name and last initial (case insensitive)" do
|
|
73
|
-
describe "when followed by no period" do
|
|
74
|
-
let(:description) { "Lunch with grace h" }
|
|
75
|
-
|
|
76
|
-
it { line_added "- #{date}: Lunch with **Grace Hopper**" }
|
|
77
|
-
it { stdout_only "Activity added: \"#{date}: Lunch with Grace Hopper\"" } if test_stdout
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
describe "when followed by a period at the end of a sentence" do
|
|
81
|
-
let(:description) { "Met grace h. So fun!" }
|
|
82
|
-
|
|
83
|
-
it { line_added "- #{date}: Met **Grace Hopper**. So fun!" }
|
|
84
|
-
it { stdout_only "Activity added: \"#{date}: Met Grace Hopper. So fun!\"" } if test_stdout
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
describe "when followed by a period at the end of the description" do
|
|
88
|
-
let(:description) { "Lunch with grace h." }
|
|
89
|
-
|
|
90
|
-
it { line_added "- #{date}: Lunch with **Grace Hopper**." }
|
|
91
|
-
it { stdout_only "Activity added: \"#{date}: Lunch with Grace Hopper.\"" } if test_stdout
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
describe "when followed by a period in the middle of a sentence" do
|
|
95
|
-
let(:description) { "Met grace h. at 12." }
|
|
96
|
-
|
|
97
|
-
it { line_added "- #{date}: Met **Grace Hopper** at 12." }
|
|
98
|
-
it { stdout_only "Activity added: \"#{date}: Met Grace Hopper at 12.\"" } if test_stdout
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
describe "when description includes a friend's nickname (case insensitive)" do
|
|
103
|
-
let(:description) { "Lunch with the admiral." }
|
|
104
|
-
|
|
105
|
-
it { line_added "- #{date}: Lunch with **Grace Hopper**." }
|
|
106
|
-
it { stdout_only "Activity added: \"#{date}: Lunch with Grace Hopper.\"" } if test_stdout
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
describe "when description includes a friend's nickname which contains a name" do
|
|
110
|
-
let(:description) { "Lunch with Amazing Grace." }
|
|
111
|
-
|
|
112
|
-
it { line_added "- #{date}: Lunch with **Grace Hopper**." }
|
|
113
|
-
it { stdout_only "Activity added: \"#{date}: Lunch with Grace Hopper.\"" } if test_stdout
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
describe "when description includes a friend's name at the beginning of a word" do
|
|
117
|
-
# Capitalization reduces chance of a false positive.
|
|
118
|
-
let(:description) { "Gracefully strolled." }
|
|
119
|
-
|
|
120
|
-
it { line_added "- #{date}: Gracefully strolled." }
|
|
121
|
-
it { stdout_only "Activity added: \"#{date}: Gracefully strolled.\"" } if test_stdout
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
describe "when description includes a friend's name at the end of a word" do
|
|
125
|
-
# Capitalization reduces chance of a false positive.
|
|
126
|
-
let(:description) { "The service was a disGrace." }
|
|
127
|
-
|
|
128
|
-
it { line_added "- #{date}: The service was a disGrace." }
|
|
129
|
-
it { stdout_only "Activity added: \"#{date}: The service was a disGrace.\"" } if test_stdout
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
describe "when description includes a friend's name in the middle of a word" do
|
|
133
|
-
# Capitalization reduces chance of a false positive.
|
|
134
|
-
let(:description) { "The service was disGraceful." }
|
|
135
|
-
|
|
136
|
-
it { line_added "- #{date}: The service was disGraceful." }
|
|
137
|
-
it { stdout_only "Activity added: \"#{date}: The service was disGraceful.\"" } if test_stdout
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
describe "when a friend's name is escaped with a backslash" do
|
|
141
|
-
# We have to use four backslashes here because of Ruby's backslash escaping; when this
|
|
142
|
-
# goes through all of the layers of this test it emerges on the other side as a single one.
|
|
143
|
-
let(:description) { "Dinner with \\\\Grace Kelly." }
|
|
144
|
-
|
|
145
|
-
it { line_added "- #{date}: Dinner with Grace Kelly." }
|
|
146
|
-
it { stdout_only "Activity added: \"#{date}: Dinner with Grace Kelly.\"" } if test_stdout
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
describe "hyphenated name edge cases" do
|
|
150
|
-
describe "when one name precedes another before a hyphen" do
|
|
151
|
-
let(:description) { "Shopped w/ Mary-Kate." }
|
|
152
|
-
|
|
153
|
-
# Make sure "Mary" is a closer friend than "Mary-Kate" so we know our
|
|
154
|
-
# test result isn't due to chance.
|
|
155
|
-
let(:content) do
|
|
156
|
-
<<-FILE
|
|
157
|
-
### Activities:
|
|
158
|
-
- 2017-01-01: Singing with **Mary Poppins**.
|
|
159
|
-
|
|
160
|
-
### Friends:
|
|
161
|
-
- Mary Poppins
|
|
162
|
-
- Mary-Kate Olsen
|
|
163
|
-
|
|
164
|
-
### Locations:
|
|
165
|
-
FILE
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
it { line_added "- #{date}: Shopped w/ **Mary-Kate Olsen**." }
|
|
169
|
-
it { stdout_only "Activity added: \"#{date}: Shopped w/ Mary-Kate Olsen.\"" } if test_stdout
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
describe "when one name follows another after a hyphen" do
|
|
173
|
-
let(:description) { "Shopped w/ Mary-Kate." }
|
|
174
|
-
|
|
175
|
-
# Make sure "Kate" is a closer friend than "Mary-Kate" so we know our
|
|
176
|
-
# test result isn't due to chance.
|
|
177
|
-
let(:content) do
|
|
178
|
-
<<-FILE
|
|
179
|
-
### Activities:
|
|
180
|
-
- 2017-01-01: Improv with **Kate Winslet**.
|
|
181
|
-
|
|
182
|
-
### Friends:
|
|
183
|
-
- Kate Winslet
|
|
184
|
-
- Mary-Kate Olsen
|
|
185
|
-
|
|
186
|
-
### Locations:
|
|
187
|
-
FILE
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
it { line_added "- #{date}: Shopped w/ **Mary-Kate Olsen**." }
|
|
191
|
-
it { stdout_only "Activity added: \"#{date}: Shopped w/ Mary-Kate Olsen.\"" } if test_stdout
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
describe "when one name is contained within another via hyphens" do
|
|
195
|
-
let(:description) { "Met Mary-Jo-Kate." }
|
|
196
|
-
|
|
197
|
-
# Make sure "Jo" is a closer friend than "Mary-Jo-Kate" so we know our
|
|
198
|
-
# test result isn't due to chance.
|
|
199
|
-
let(:content) do
|
|
200
|
-
<<-FILE
|
|
201
|
-
### Activities:
|
|
202
|
-
- 2017-01-01: Singing with **Jo Stafford**.
|
|
203
|
-
|
|
204
|
-
### Friends:
|
|
205
|
-
- Jo Stafford
|
|
206
|
-
- Mary-Jo-Kate Olsen
|
|
207
|
-
|
|
208
|
-
### Locations:
|
|
209
|
-
FILE
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
it { line_added "- #{date}: Met **Mary-Jo-Kate Olsen**." }
|
|
213
|
-
it { stdout_only "Activity added: \"#{date}: Met Mary-Jo-Kate Olsen.\"" } if test_stdout
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
describe "when description has a friend's name with leading asterisks" do
|
|
218
|
-
let(:description) { "Lunch with **Grace Hopper." }
|
|
219
|
-
|
|
220
|
-
it { line_added "- #{date}: Lunch with **Grace Hopper." }
|
|
221
|
-
it { stdout_only "Activity added: \"#{date}: Lunch with **Grace Hopper.\"" } if test_stdout
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
describe "when description has a friend's name with trailing asterisks" do
|
|
225
|
-
# Note: We can't guarantee that "Grace Hopper**" doesn't match because the "Grace" isn't
|
|
226
|
-
# surrounded by asterisks.
|
|
227
|
-
let(:description) { "Lunch with Grace**." }
|
|
228
|
-
|
|
229
|
-
it { line_added "- #{date}: Lunch with Grace**." }
|
|
230
|
-
it { stdout_only "Activity added: \"#{date}: Lunch with Grace**.\"" } if test_stdout
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
describe "when description has a friend's name multiple times" do
|
|
234
|
-
let(:description) { "Grace! Grace!!!" }
|
|
235
|
-
|
|
236
|
-
it { line_added "- #{date}: **Grace Hopper**! **Grace Hopper**!!!" }
|
|
237
|
-
it { stdout_only "Activity added: \"#{date}: Grace Hopper! Grace Hopper!!!\"" } if test_stdout
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
describe "when description has a name with multiple friend matches" do
|
|
241
|
-
describe "when there is useful context from past activities" do
|
|
242
|
-
let(:description) { "Met John + Elizabeth." }
|
|
243
|
-
|
|
244
|
-
# Create a past activity in which Elizabeth Cady Stanton did something
|
|
245
|
-
# with John Cage. Then, create past activities to make Elizabeth II a
|
|
246
|
-
# better friend than Elizabeth Cady Stanton.
|
|
247
|
-
let(:content) do
|
|
248
|
-
<<-FILE
|
|
249
|
-
### Activities:
|
|
250
|
-
- 2017-01-05: Picnic with **Elizabeth Cady Stanton** and **John Cage**.
|
|
251
|
-
- 2017-01-04: Got lunch with **Elizabeth II**.
|
|
252
|
-
- 2017-01-03: Ice skated with **Elizabeth II**.
|
|
253
|
-
|
|
254
|
-
### Friends:
|
|
255
|
-
- Elizabeth Cady Stanton
|
|
256
|
-
- Elizabeth II
|
|
257
|
-
- John Cage
|
|
258
|
-
|
|
259
|
-
### Locations:
|
|
260
|
-
FILE
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
# Elizabeth II is the better friend, but historical activities have
|
|
264
|
-
# had Elizabeth Cady Stanton and John Cage together. Thus, we should
|
|
265
|
-
# interpret "Elizabeth" as Elizabeth Cady Stanton.
|
|
266
|
-
it { line_added "- #{date}: Met **John Cage** + **Elizabeth Cady Stanton**." }
|
|
267
|
-
if test_stdout
|
|
268
|
-
it { stdout_only "Activity added: \"#{date}: Met John Cage + Elizabeth Cady Stanton.\"" }
|
|
269
|
-
end
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
describe "when there is no useful context from past activities" do
|
|
273
|
-
let(:description) { "Dinner with John and Elizabeth." }
|
|
274
|
-
|
|
275
|
-
# Create a past activity in which Elizabeth Cady Stanton did something
|
|
276
|
-
# with John Cage. Then, create past activities to make Elizabeth II a
|
|
277
|
-
# better friend than Elizabeth Cady Stanton.
|
|
278
|
-
let(:content) do
|
|
279
|
-
<<-FILE
|
|
280
|
-
### Activities:
|
|
281
|
-
- 2017-01-03: Ice skated with **Elizabeth II**.
|
|
282
|
-
|
|
283
|
-
### Friends:
|
|
284
|
-
- Elizabeth Cady Stanton
|
|
285
|
-
- Elizabeth II
|
|
286
|
-
- John Cage
|
|
287
|
-
|
|
288
|
-
### Locations:
|
|
289
|
-
FILE
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
# Pick the "Elizabeth" with more activities.
|
|
293
|
-
it { line_added "- #{date}: Dinner with **John Cage** and **Elizabeth II**." }
|
|
294
|
-
if test_stdout
|
|
295
|
-
it { stdout_only "Activity added: \"#{date}: Dinner with John Cage and Elizabeth II.\"" }
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
describe "when description contains a location name (case insensitive)" do
|
|
301
|
-
let(:description) { "Lunch at a cafe in paris." }
|
|
302
|
-
|
|
303
|
-
it { line_added "- #{date}: Lunch at a cafe in _Paris_." }
|
|
304
|
-
it { stdout_only "Activity added: \"#{date}: Lunch at a cafe in Paris.\"" } if test_stdout
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
describe "when description contains both names and locations" do
|
|
308
|
-
let(:description) { "Grace and I went to Atlantis and then Paris for lunch with George." }
|
|
309
|
-
|
|
310
|
-
it do
|
|
311
|
-
line_added "- #{date}: **Grace Hopper** and I went to _Atlantis_ and then _Paris_ for "\
|
|
312
|
-
"lunch with **George Washington Carver**."
|
|
313
|
-
end
|
|
314
|
-
if test_stdout
|
|
315
|
-
it do
|
|
316
|
-
stdout_only "Activity added: \"#{date}: Grace Hopper and I went to Atlantis and then "\
|
|
317
|
-
"Paris for lunch with George Washington Carver.\""
|
|
318
|
-
end
|
|
319
|
-
end
|
|
320
|
-
end
|
|
321
|
-
end
|
|
322
|
-
end
|
|
6
|
+
require "./test/add_event_helper"
|
|
323
7
|
|
|
324
8
|
clean_describe "add activity" do
|
|
325
9
|
let(:content) { CONTENT }
|
|
@@ -332,6 +16,8 @@ clean_describe "add activity" do
|
|
|
332
16
|
- 2017-01-01: Activity 1.
|
|
333
17
|
- 2016-01-01: Activity one year earlier.
|
|
334
18
|
|
|
19
|
+
### Notes:
|
|
20
|
+
|
|
335
21
|
### Friends:
|
|
336
22
|
|
|
337
23
|
### Locations:
|
|
@@ -356,6 +42,8 @@ FILE
|
|
|
356
42
|
- 2017-01-01: Activity 1.
|
|
357
43
|
- 2016-01-01: Activity one year earlier.
|
|
358
44
|
|
|
45
|
+
### Notes:
|
|
46
|
+
|
|
359
47
|
### Friends:
|
|
360
48
|
|
|
361
49
|
### Locations:
|
|
@@ -363,37 +51,5 @@ FILE
|
|
|
363
51
|
end
|
|
364
52
|
end
|
|
365
53
|
|
|
366
|
-
|
|
367
|
-
subject { run_cmd("add activity #{date}: #{description}") }
|
|
368
|
-
|
|
369
|
-
date_parsing_specs
|
|
370
|
-
description_parsing_specs
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
describe "when given only a date in the command" do
|
|
374
|
-
subject { run_cmd("add activity #{date}", stdin_data: description) }
|
|
375
|
-
|
|
376
|
-
# We don't try to test the STDOUT here because our command prompt produces other STDOUT that's
|
|
377
|
-
# hard to test.
|
|
378
|
-
date_parsing_specs(test_stdout: false)
|
|
379
|
-
description_parsing_specs(test_stdout: false)
|
|
380
|
-
end
|
|
381
|
-
|
|
382
|
-
describe "when given only a description in the command" do
|
|
383
|
-
subject { run_cmd("add activity #{description}") }
|
|
384
|
-
|
|
385
|
-
# We don't test date parsing since in this case the date is always inferred to be today.
|
|
386
|
-
|
|
387
|
-
description_parsing_specs
|
|
388
|
-
end
|
|
389
|
-
|
|
390
|
-
describe "when given neither a date nor a description in the command" do
|
|
391
|
-
subject { run_cmd("add activity", stdin_data: description) }
|
|
392
|
-
|
|
393
|
-
# We don't test date parsing since in this case the date is always inferred to be today.
|
|
394
|
-
|
|
395
|
-
# We don't try to test the STDOUT here because our command prompt produces other STDOUT that's
|
|
396
|
-
# hard to test.
|
|
397
|
-
description_parsing_specs(test_stdout: false)
|
|
398
|
-
end
|
|
54
|
+
parsing_specs(event: :activity)
|
|
399
55
|
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "date"
|
|
4
|
+
|
|
5
|
+
require "./test/helper"
|
|
6
|
+
require "./test/add_event_helper"
|
|
7
|
+
|
|
8
|
+
clean_describe "add note" do
|
|
9
|
+
let(:content) { CONTENT }
|
|
10
|
+
|
|
11
|
+
describe "date ordering" do
|
|
12
|
+
let(:content) do
|
|
13
|
+
<<-FILE
|
|
14
|
+
### Activities:
|
|
15
|
+
|
|
16
|
+
### Notes:
|
|
17
|
+
- 2018-01-01: Note one year later.
|
|
18
|
+
- 2017-01-01: Note 1.
|
|
19
|
+
- 2016-01-01: Note one year earlier.
|
|
20
|
+
|
|
21
|
+
### Friends:
|
|
22
|
+
|
|
23
|
+
### Locations:
|
|
24
|
+
FILE
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
subject do
|
|
28
|
+
4.times do |i|
|
|
29
|
+
run_cmd("add note 2017-01-01: Note #{i + 2}.")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "orders dates by insertion time" do
|
|
34
|
+
subject
|
|
35
|
+
File.read(filename).must_equal <<-FILE
|
|
36
|
+
### Activities:
|
|
37
|
+
|
|
38
|
+
### Notes:
|
|
39
|
+
- 2018-01-01: Note one year later.
|
|
40
|
+
- 2017-01-01: Note 5.
|
|
41
|
+
- 2017-01-01: Note 4.
|
|
42
|
+
- 2017-01-01: Note 3.
|
|
43
|
+
- 2017-01-01: Note 2.
|
|
44
|
+
- 2017-01-01: Note 1.
|
|
45
|
+
- 2016-01-01: Note one year earlier.
|
|
46
|
+
|
|
47
|
+
### Friends:
|
|
48
|
+
|
|
49
|
+
### Locations:
|
|
50
|
+
FILE
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
parsing_specs(event: :note)
|
|
55
|
+
end
|
data/test/commands/clean_spec.rb
CHANGED
|
@@ -25,6 +25,8 @@ clean_describe "clean" do
|
|
|
25
25
|
file_equals <<-FILE
|
|
26
26
|
### Activities:
|
|
27
27
|
|
|
28
|
+
### Notes:
|
|
29
|
+
|
|
28
30
|
### Friends:
|
|
29
31
|
|
|
30
32
|
### Locations:
|
|
@@ -33,10 +35,30 @@ clean_describe "clean" do
|
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
describe "when file has content" do
|
|
36
|
-
|
|
38
|
+
describe "when content is formatted correctly" do
|
|
39
|
+
let(:content) { SCRAMBLED_CONTENT }
|
|
40
|
+
|
|
41
|
+
it "writes the file with contents sorted" do
|
|
42
|
+
file_equals CONTENT
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "when a header is malformed" do
|
|
47
|
+
let(:content) do
|
|
48
|
+
<<-FILE
|
|
49
|
+
### Activities:
|
|
50
|
+
|
|
51
|
+
### Garbage:
|
|
52
|
+
|
|
53
|
+
### Friends:
|
|
54
|
+
|
|
55
|
+
### Locations:
|
|
56
|
+
FILE
|
|
57
|
+
end
|
|
37
58
|
|
|
38
|
-
|
|
39
|
-
|
|
59
|
+
it "prints an error message" do
|
|
60
|
+
stderr_only 'Error: Expected "a valid header" on line 3'
|
|
61
|
+
end
|
|
40
62
|
end
|
|
41
63
|
end
|
|
42
64
|
end
|