usaidwat 1.3.0 → 1.4.0

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.
@@ -16,6 +16,18 @@ module USaidWat
16
16
  end
17
17
  end
18
18
 
19
+ class MockSubmission
20
+ attr_reader :subreddit, :title, :created_utc, :permalink
21
+
22
+ def initialize(dict)
23
+ data = dict['data']
24
+ @subreddit = data['subreddit']
25
+ @title = data['title']
26
+ @created_utc = data['created_utc']
27
+ @permalink = data['permalink']
28
+ end
29
+ end
30
+
19
31
  class MockUser
20
32
  def initialize(username)
21
33
  @username = username
@@ -30,6 +42,11 @@ module USaidWat
30
42
  json['data']['children'].map { |d| MockComment.new(d) }
31
43
  end
32
44
 
45
+ def posts
46
+ json = load_data("submissions_#{@username}.json")
47
+ json['data']['children'].map { |d| MockSubmission.new(d) }
48
+ end
49
+
33
50
  private
34
51
 
35
52
  def load_data(data_file)
@@ -1,3 +1,3 @@
1
1
  module USaidWat
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require 'usaidwat/ext/array'
3
+
4
+ module USaidWat
5
+ module Ext
6
+ describe Array do
7
+ it "should split args separated by spaces" do
8
+ v = %W{one two three}
9
+ expected = v
10
+ actual = v.subreddits
11
+ expect(actual).to eq(expected)
12
+ end
13
+
14
+ it "should split args separated by commas" do
15
+ v = ['one,two,three']
16
+ expected = %W{one two three}
17
+ actual = v.subreddits
18
+ expect(actual).to eq(expected)
19
+ end
20
+
21
+ it "should split args separated by plus signs" do
22
+ v = ['one+two+three']
23
+ expected = %W{one two three}
24
+ actual = v.subreddits
25
+ expect(actual).to eq(expected)
26
+ end
27
+
28
+ it "should downcase all args" do
29
+ v = %W{one Two Three}
30
+ expected = %W{one two three}
31
+ actual = v.subreddits
32
+ expect(actual).to eq(expected)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -26,6 +26,8 @@ module USaidWat
26
26
  to_return(:body => IO.read(File.join(root, "mipadi.json")))
27
27
  stub_request(:get, "http://www.reddit.com/user/mipadi/about.json").
28
28
  to_return(:body => IO.read(File.join(root, "user_mipadi.json")))
29
+ stub_request(:get, "http://www.reddit.com/user/mipadi/submitted.json?after=&limit=25").
30
+ to_return(:body => IO.read(File.join(root, "submissions_mipadi.json")))
29
31
 
30
32
  Timecop.freeze(Time.new(2015, 9, 15, 11, 14, 30, "-07:00"))
31
33
  end
@@ -34,6 +36,12 @@ module USaidWat
34
36
  Timecop.return
35
37
  end
36
38
 
39
+ describe "#posts" do
40
+ it "retrieves 25 posts" do
41
+ expect(redditor.posts.count).to eq(25)
42
+ end
43
+ end
44
+
37
45
  describe "#comments" do
38
46
  it "retrieves 100 comments" do
39
47
  expect(redditor.comments.count).to eq(100)
@@ -76,6 +84,14 @@ module USaidWat
76
84
  to_return(:status => 404, :body => IO.read(File.join(root, "testuser.json")))
77
85
  stub_request(:get, "http://www.reddit.com/user/testuser/about.json").
78
86
  to_return(:status => 404, :body => IO.read(File.join(root, "user_testuser.json")))
87
+ stub_request(:get, "http://www.reddit.com/user/testuser/submitted.json?after=&limit=25").
88
+ to_return(:status => 404, :body => IO.read(File.join(root, "submissions_testuser.json")))
89
+ end
90
+
91
+ describe "#posts" do
92
+ it "raises an exception if the user does not exist" do
93
+ expect { Redditor.new("testuser").comments }.to raise_error(NoSuchUserError, /testuser/)
94
+ end
79
95
  end
80
96
 
81
97
  describe "#comments" do
@@ -117,6 +133,14 @@ module USaidWat
117
133
  to_return(:status => 500)
118
134
  stub_request(:get, "http://www.reddit.com/user/mipadi/about.json").
119
135
  to_return(:status => 500)
136
+ stub_request(:get, "http://www.reddit.com/user/mipadi/submitted.json?after=&limit=25").
137
+ to_return(:status => 500)
138
+ end
139
+
140
+ describe "#posts" do
141
+ it "raises 'Reddit unreachable' error" do
142
+ expect { redditor.comments }.to raise_error(ReachabilityError, /Reddit unreachable/)
143
+ end
120
144
  end
121
145
 
122
146
  describe "#comments" do
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'usaidwat/algo'
3
+ require 'usaidwat/count'
4
+
5
+
6
+ module USaidWat
7
+ module Application
8
+ describe CountCommand do
9
+ before(:all) do
10
+ Struct.new('Comment', :subreddit, :body)
11
+ end
12
+
13
+ let (:stub) { Class.new { include CountCommand }.new }
14
+
15
+ let(:comments) do
16
+ c1 = Array.new(20) { Struct::Comment.new('AskReddit') }
17
+ c2 = Array.new(20) { Struct::Comment.new('programming') }
18
+ c3 = Array.new(19) { Struct::Comment.new('Python') }
19
+ c4 = Array.new(20) { Struct::Comment.new('books') }
20
+ c5 = Array.new(21) { Struct::Comment.new('ruby') }
21
+ c1 + c2 + c3 + c4 + c5
22
+ end
23
+
24
+ describe '#algorithm' do
25
+ it 'sorts entries by subreddit name' do
26
+ expect(stub.algorithm(true)).to eq(USaidWat::Algorithms::CountAlgorithm)
27
+ end
28
+
29
+ it 'sorts entries by count' do
30
+ expect(stub.algorithm(false)).to eq(USaidWat::Algorithms::LexicographicalAlgorithm)
31
+ end
32
+ end
33
+
34
+ describe '#partition' do
35
+ it 'partitions data and returns the longest subreddit' do
36
+ res = stub.partition(comments, false)
37
+ expect(res.longest).to eq('programming'.length)
38
+ end
39
+
40
+ it 'partitions data and returns the partitioned data' do
41
+ res = stub.partition(comments, false)
42
+ expect(res.counts.count).to eq(5)
43
+ expect(res.counts.first.first).to eq('AskReddit')
44
+ expect(res.counts.last.first).to eq('ruby')
45
+ end
46
+
47
+ it 'partitions data, sorting by count, and returns the longest subreddit' do
48
+ res = stub.partition(comments, true)
49
+ expect(res.longest).to eq('programming'.length)
50
+ end
51
+
52
+ it 'partitions data, sorting by count, and returns the partitioned data' do
53
+ res = stub.partition(comments, true)
54
+ expect(res.counts.count).to eq(5)
55
+ expect(res.counts.first.first).to eq('ruby')
56
+ expect(res.counts.last.first).to eq('Python')
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require 'usaidwat/filter'
3
+
4
+ module USaidWat
5
+ module Application
6
+ describe FilterCommand do
7
+ before(:all) do
8
+ Struct.new('Redditor', :username)
9
+ Struct.new('Comment', :subreddit, :body) unless Struct::const_defined? 'Comment'
10
+ end
11
+
12
+ let (:stub) { Class.new { include FilterCommand }.new }
13
+ let (:redditor) { Struct::Redditor.new('mipadi') }
14
+
15
+ let (:comments) do
16
+ c1 = Array.new(50) { Struct::Comment.new('AskReddit', 'The quick brown fox jumps over the lazy dog.') }
17
+ c2 = Array.new(50) { Struct::Comment.new('Python', 'How razorback-jumping frogs can level six piqued gynmasts!') }
18
+ c1 + c2
19
+ end
20
+
21
+ describe '#filter_entries' do
22
+ it 'returns entries filtered by subreddit' do
23
+ res = stub.filter_entries('', redditor, comments, ['python'])
24
+ expect(res.right?).to be true
25
+ expect(res.value.count).to eq(50)
26
+ end
27
+
28
+ it 'returns an empty object if all entries are filtered' do
29
+ res = stub.filter_entries('', redditor, comments, ['nsfw'])
30
+ expect(res.left?).to be true
31
+ end
32
+
33
+ it 'returns all the entries if no subreddit is specified' do
34
+ res = stub.filter_entries('', redditor, comments, [])
35
+ expect(res.right?).to be true
36
+ expect(res.value).to eq(comments)
37
+ end
38
+ end
39
+
40
+ describe '#grep_entries' do
41
+ it 'returns entries filtered by search string' do
42
+ res = stub.grep_entries('', redditor, comments, 'fox')
43
+ expect(res.right?).to be true
44
+ expect(res.value.count).to eq(50)
45
+ end
46
+
47
+ it 'returns an empty object if all entries are filtered' do
48
+ res = stub.grep_entries('', redditor, comments, 'blah')
49
+ expect(res.left?).to be true
50
+ end
51
+
52
+ it 'returns all the entries if no search string is specified' do
53
+ res = stub.grep_entries('', redditor, comments, nil)
54
+ expect(res.right?).to be true
55
+ expect(res.value).to eq(comments)
56
+ end
57
+ end
58
+
59
+ describe '#limit_entries' do
60
+ it 'returns a specified number of entries' do
61
+ entries = (1..100).to_a
62
+ res = stub.limit_entries('', nil, entries, 10)
63
+ expect(res.right?).to be true
64
+ expect(res.value.count).to eq(10)
65
+ end
66
+
67
+ it 'returns all the entries if the limit is nil' do
68
+ entries = (1..100).to_a
69
+ res = stub.limit_entries('', nil, entries, nil)
70
+ expect(res.right?).to be true
71
+ expect(res.value.count).to eq(entries.count)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -88,6 +88,74 @@ module USaidWat
88
88
  end
89
89
  end
90
90
 
91
+ describe PostFormatter do
92
+ let(:formatter) { PostFormatter.new }
93
+
94
+ before do
95
+ Timecop.freeze(Time.new(2015, 11, 19, 15, 27))
96
+ end
97
+
98
+ after do
99
+ Timecop.return
100
+ end
101
+
102
+ describe "#format" do
103
+ it "should return a string containing the formatted post" do
104
+ post = double("post")
105
+ expect(post).to receive(:subreddit).and_return("Games")
106
+ expect(post).to receive(:permalink).and_return("/r/Games/comments/3ovldc/the_xbox_one_is_garbage_and_the_future_is_bullshit/")
107
+ expect(post).to receive(:title).and_return("The Xbox One Is Garbage And The Future Is Bullshit")
108
+ expect(post).to receive(:created_utc).and_return(1444928064)
109
+ expected = <<-EXPECTED
110
+ Games
111
+ https://www.reddit.com/r/Games/comments/3ovldc
112
+ The Xbox One Is Garbage And The Future Is Bullshit
113
+ about 1 month ago
114
+ EXPECTED
115
+ expected = expected.strip
116
+ actual = formatter.format(post).delete_ansi_color_codes
117
+ expect(actual).to eq(expected)
118
+ end
119
+
120
+ it "should print two spaces between posts" do
121
+ post1 = double("first post")
122
+ expect(post1).to receive(:subreddit).and_return("Games")
123
+ expect(post1).to receive(:permalink).and_return("/r/Games/comments/3ovldc/the_xbox_one_is_garbage_and_the_future_is_bullshit/")
124
+ expect(post1).to receive(:title).and_return("The Xbox One Is Garbage And The Future Is Bullshit")
125
+ expect(post1).to receive(:created_utc).and_return(1444928064)
126
+ post2 = double("second post")
127
+ expect(post2).to receive(:subreddit).and_return("technology")
128
+ expect(post2).to receive(:permalink).and_return("/r/technology/comments/3o0vrh/mozilla_lays_out_a_proposed_set_of_rules_for/")
129
+ expect(post2).to receive(:title).and_return("Mozilla lays out a proposed set of rules for content blockers")
130
+ expect(post2).to receive(:created_utc).and_return(1444340278)
131
+ s = formatter.format(post1)
132
+ s = formatter.format(post2)
133
+ lines = s.split("\n")
134
+ expect(lines[0]).to eq('')
135
+ expect(lines[1]).to eq('')
136
+ expect(lines[2]).to eq('')
137
+ expect(lines[3]).not_to eq('')
138
+ end
139
+
140
+ it "should truncate titles to 80 characters" do
141
+ post = double("post")
142
+ expect(post).to receive(:subreddit).and_return("webdev")
143
+ expect(post).to receive(:permalink).and_return("/r/webdev/comments/29og3m/sick_of_ruby_dynamic_typing_side_effects_and/")
144
+ expect(post).to receive(:title).and_return("Sick of Ruby, dynamic typing, side effects, and basically object-oriented programming")
145
+ expect(post).to receive(:created_utc).and_return(1404331670)
146
+ expected = <<-EXPECTED
147
+ webdev
148
+ https://www.reddit.com/r/webdev/comments/29og3m
149
+ Sick of Ruby, dynamic typing, side effects, and basically object-oriented progra
150
+ about a year ago
151
+ EXPECTED
152
+ expected = expected.strip
153
+ actual = formatter.format(post).delete_ansi_color_codes
154
+ expect(actual).to eq(expected)
155
+ end
156
+ end
157
+ end
158
+
91
159
  describe CommentFormatter do
92
160
  let(:formatter) { CommentFormatter.new }
93
161
 
@@ -200,5 +268,29 @@ EXPECTED
200
268
  end
201
269
  end
202
270
  end
271
+
272
+ describe TallyFormatter do
273
+ before(:all) do
274
+ Struct.new('PartitionData', :longest, :counts)
275
+ end
276
+
277
+ let (:formatter) { TallyFormatter.new }
278
+
279
+ describe '#format' do
280
+ it 'should format partitioned data' do
281
+ longest_subreddit = 'writing'.length
282
+ count_data = [['apple', 5], ['Bass', 1], ['Python', 3], ['writing', 10]]
283
+ partition = Struct::PartitionData.new(longest_subreddit, count_data)
284
+ expected = <<-EOS
285
+ apple 5
286
+ Bass 1
287
+ Python 3
288
+ writing 10
289
+ EOS
290
+ actual = formatter.format(partition)
291
+ expect(actual).to eq(expected)
292
+ end
293
+ end
294
+ end
203
295
  end
204
296
  end
data/usaidwat.gemspec CHANGED
@@ -28,12 +28,12 @@ Gem::Specification.new do |gem|
28
28
 
29
29
  gem.required_ruby_version = '>= 1.9.3'
30
30
 
31
- gem.add_runtime_dependency('downterm', '~> 0.1.3')
32
- gem.add_runtime_dependency('highline', '~> 1.7')
31
+ gem.add_runtime_dependency('downterm', '~> 0.1.4')
33
32
  gem.add_runtime_dependency('mercenary', '~> 0.3.5')
34
33
  gem.add_runtime_dependency('rainbow', '~> 2.0')
35
34
  gem.add_runtime_dependency('snooby', '~> 0.1.5')
36
35
  gem.add_runtime_dependency('sysexits', '~> 1.2')
36
+ gem.add_runtime_dependency('ttycaca', '~> 1.0')
37
37
 
38
38
  gem.add_development_dependency('aruba', '~> 0.9')
39
39
  gem.add_development_dependency('cucumber', '~> 2.0')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: usaidwat
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Dippery
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-04 00:00:00.000000000 Z
11
+ date: 2016-01-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: downterm
@@ -16,28 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.1.3
19
+ version: 0.1.4
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.1.3
27
- - !ruby/object:Gem::Dependency
28
- name: highline
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.7'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.7'
26
+ version: 0.1.4
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: mercenary
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +80,20 @@ dependencies:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
82
  version: '1.2'
83
+ - !ruby/object:Gem::Dependency
84
+ name: ttycaca
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: aruba
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -172,6 +172,7 @@ executables:
172
172
  extensions: []
173
173
  extra_rdoc_files: []
174
174
  files:
175
+ - ".gitattributes"
175
176
  - ".gitignore"
176
177
  - Gemfile
177
178
  - LICENSE.txt
@@ -180,46 +181,54 @@ files:
180
181
  - bin/usaidwat
181
182
  - features/fixtures/blank.json
182
183
  - features/fixtures/mipadi.json
184
+ - features/fixtures/submissions_blank.json
185
+ - features/fixtures/submissions_mipadi.json
186
+ - features/fixtures/submissions_testuser.json
183
187
  - features/fixtures/testuser.json
184
188
  - features/fixtures/user_mipadi.json
185
189
  - features/fixtures/user_testuser.json
186
190
  - features/help.feature
187
191
  - features/log.feature
192
+ - features/posts.feature
188
193
  - features/step_definitions/reddit_steps.rb
189
194
  - features/step_definitions/time_steps.rb
190
195
  - features/support/aruba.rb
191
- - features/support/time.rb
192
196
  - features/tally.feature
193
197
  - features/user.feature
194
198
  - lib/usaidwat.rb
195
199
  - lib/usaidwat/algo.rb
196
200
  - lib/usaidwat/application.rb
197
201
  - lib/usaidwat/client.rb
202
+ - lib/usaidwat/count.rb
198
203
  - lib/usaidwat/either.rb
204
+ - lib/usaidwat/ext/array.rb
205
+ - lib/usaidwat/ext/mercenary.rb
199
206
  - lib/usaidwat/ext/string.rb
200
207
  - lib/usaidwat/ext/time.rb
208
+ - lib/usaidwat/filter.rb
201
209
  - lib/usaidwat/formatter.rb
202
210
  - lib/usaidwat/pager.rb
203
211
  - lib/usaidwat/service.rb
204
- - lib/usaidwat/terminal.rb
205
212
  - lib/usaidwat/version.rb
206
213
  - spec/spec_helper.rb
207
214
  - spec/usaidwat/algo_spec.rb
215
+ - spec/usaidwat/array_spec.rb
208
216
  - spec/usaidwat/client_spec.rb
217
+ - spec/usaidwat/count_spec.rb
209
218
  - spec/usaidwat/either_spec.rb
219
+ - spec/usaidwat/filter_spec.rb
210
220
  - spec/usaidwat/formatter_spec.rb
211
221
  - spec/usaidwat/service_spec.rb
212
222
  - spec/usaidwat/string_spec.rb
213
- - spec/usaidwat/terminal_spec.rb
214
223
  - spec/usaidwat/time_spec.rb
215
224
  - usaidwat.gemspec
216
225
  homepage: https://github.com/mdippery/usaidwat
217
226
  licenses:
218
227
  - MIT
219
228
  metadata:
220
- build_date: 2015-11-03 19:55:52 PST
221
- commit: v1.3.0
222
- commit_hash: 2ac920497d08c42b67f40bda4e78496e1b9ad6c4
229
+ build_date: 2016-01-06 19:17:01 PST
230
+ commit: v1.4.0
231
+ commit_hash: 7ce44f2d344c06795cac025f343bd8d23f7faa95
223
232
  post_install_message:
224
233
  rdoc_options: []
225
234
  require_paths:
@@ -243,23 +252,28 @@ summary: Answers the age-old question, "Where does a Redditor comment the most?"
243
252
  test_files:
244
253
  - features/fixtures/blank.json
245
254
  - features/fixtures/mipadi.json
255
+ - features/fixtures/submissions_blank.json
256
+ - features/fixtures/submissions_mipadi.json
257
+ - features/fixtures/submissions_testuser.json
246
258
  - features/fixtures/testuser.json
247
259
  - features/fixtures/user_mipadi.json
248
260
  - features/fixtures/user_testuser.json
249
261
  - features/help.feature
250
262
  - features/log.feature
263
+ - features/posts.feature
251
264
  - features/step_definitions/reddit_steps.rb
252
265
  - features/step_definitions/time_steps.rb
253
266
  - features/support/aruba.rb
254
- - features/support/time.rb
255
267
  - features/tally.feature
256
268
  - features/user.feature
257
269
  - spec/spec_helper.rb
258
270
  - spec/usaidwat/algo_spec.rb
271
+ - spec/usaidwat/array_spec.rb
259
272
  - spec/usaidwat/client_spec.rb
273
+ - spec/usaidwat/count_spec.rb
260
274
  - spec/usaidwat/either_spec.rb
275
+ - spec/usaidwat/filter_spec.rb
261
276
  - spec/usaidwat/formatter_spec.rb
262
277
  - spec/usaidwat/service_spec.rb
263
278
  - spec/usaidwat/string_spec.rb
264
- - spec/usaidwat/terminal_spec.rb
265
279
  - spec/usaidwat/time_spec.rb