stockboy 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +7 -2
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +6 -3
  6. data/lib/stockboy/configurator.rb +3 -1
  7. data/lib/stockboy/filters.rb +0 -9
  8. data/lib/stockboy/job.rb +3 -3
  9. data/lib/stockboy/provider.rb +6 -8
  10. data/lib/stockboy/provider_repeater.rb +2 -3
  11. data/lib/stockboy/providers/file.rb +32 -21
  12. data/lib/stockboy/providers/ftp.rb +6 -2
  13. data/lib/stockboy/providers/http.rb +13 -10
  14. data/lib/stockboy/providers/imap.rb +47 -24
  15. data/lib/stockboy/providers/imap/search_options.rb +1 -1
  16. data/lib/stockboy/providers/soap.rb +3 -2
  17. data/lib/stockboy/railtie.rb +1 -0
  18. data/lib/stockboy/reader.rb +2 -0
  19. data/lib/stockboy/readers/spreadsheet.rb +1 -0
  20. data/lib/stockboy/registry.rb +4 -8
  21. data/lib/stockboy/version.rb +1 -1
  22. data/spec/fixtures/email/csv_attachment.eml +20 -0
  23. data/spec/spec_helper.rb +24 -2
  24. data/spec/stockboy/configurator_spec.rb +54 -3
  25. data/spec/stockboy/filter_spec.rb +7 -0
  26. data/spec/stockboy/job_spec.rb +65 -2
  27. data/spec/stockboy/provider_repeater_spec.rb +1 -1
  28. data/spec/stockboy/provider_spec.rb +21 -0
  29. data/spec/stockboy/providers/file_spec.rb +38 -18
  30. data/spec/stockboy/providers/http_spec.rb +1 -10
  31. data/spec/stockboy/providers/imap/search_options_spec.rb +13 -2
  32. data/spec/stockboy/providers/imap_spec.rb +83 -5
  33. data/spec/stockboy/providers/soap_spec.rb +1 -1
  34. data/spec/stockboy/reader_spec.rb +26 -0
  35. data/spec/stockboy/readers/spreadsheet_spec.rb +1 -1
  36. data/spec/stockboy/readers/xml_spec.rb +1 -1
  37. data/spec/stockboy/translations_spec.rb +25 -0
  38. metadata +27 -23
@@ -93,22 +93,13 @@ module Stockboy
93
93
  provider.username = "username"
94
94
  provider.password = "password"
95
95
 
96
- allow(HTTPI).to receive(:request) { response }
96
+ expect(HTTPI).to receive(:request) { response }
97
97
  expect_any_instance_of(HTTPI::Auth::Config).to receive(:basic).with("username", "password")
98
98
 
99
99
  provider.data.should == '{"success":true}'
100
100
  end
101
101
  end
102
102
 
103
- describe "#client" do
104
- it "yields a generic HTTP interface" do
105
- provider.client do |http|
106
- http.should respond_to :get
107
- http.should respond_to :post
108
- end
109
- end
110
- end
111
-
112
103
  end
113
104
  end
114
105
 
@@ -28,8 +28,19 @@ module Stockboy::Providers
28
28
 
29
29
  DATE_OPTIONS.each do |date_option_symbol, date_option_imap|
30
30
  it "converts #{date_option_imap.inspect} to IMAP date option" do
31
- options(date_option_symbol => Time.new(2012, 12, 12))
32
- .to_imap.should == [date_option_imap, "12-DEC-2012"]
31
+ options(date_option_symbol => TIME_FORMATS.first)
32
+ .to_imap.should == [date_option_imap, "12-DEC-2012"]
33
+ end
34
+ end
35
+
36
+ TIME_FORMATS = [ t = Time.new(2012, 12, 12),
37
+ t.to_i,
38
+ t.to_s ]
39
+
40
+ TIME_FORMATS.each do |time|
41
+ it "converts #{time.class} to IMAP date option" do
42
+ options(since: time)
43
+ .to_imap.should == ["SINCE", "12-DEC-2012"]
33
44
  end
34
45
  end
35
46
 
@@ -57,14 +57,92 @@ module Stockboy
57
57
  end
58
58
 
59
59
  describe "#data" do
60
+ let(:imap) { double("Net::IMAP") }
61
+ let(:provider) { described_class.new(host: 'h', username: 'u', password: 'p') }
62
+ subject(:data) { provider.data }
63
+ before { allow(provider).to receive(:client).and_yield imap }
60
64
 
61
65
  context "with no messages found" do
62
- it "should be nil" do
63
- allow(provider).to receive(:fetch_imap_message_keys).and_return []
64
- provider.data.should be_nil
66
+ before { mock_imap_search [] => [] }
67
+ it { should be_nil }
68
+ end
69
+
70
+ context "with a found message" do
71
+ let(:rfc_email) { File.read(fixture_path "email/csv_attachment.eml") }
72
+ before { mock_imap_search [] => [1] and mock_imap_fetch 1 => rfc_email }
73
+ it { should match "LAST_NAME,FIRST_NAME" }
74
+
75
+ context "validating correct filename string" do
76
+ before { provider.attachment = "daily_report.csv" }
77
+ it { should match "LAST_NAME,FIRST_NAME" }
78
+ end
79
+
80
+ context "validating incorrect filename string" do
81
+ before { provider.attachment = "wrong_report.csv" }
82
+ it { should be_nil }
83
+ end
84
+
85
+ context "validating correct filename pattern" do
86
+ before { provider.attachment = /^daily.*\.csv$/ }
87
+ it { should match "LAST_NAME,FIRST_NAME" }
88
+ end
89
+
90
+ context "validating incorrect filename pattern" do
91
+ before { provider.attachment = /^wrong.*\.csv$/ }
92
+ it { should be_nil }
93
+ end
94
+
95
+ context "validating correct smaller size" do
96
+ before { provider.smaller_than = 2048 }
97
+ it { should match "LAST_NAME,FIRST_NAME" }
98
+ end
99
+
100
+ context "validating incorrect smaller size" do
101
+ before { provider.smaller_than = 10 }
102
+ it { should be_nil }
65
103
  end
104
+
105
+ context "validating correct larger size" do
106
+ before { provider.larger_than = 10 }
107
+ it { should match "LAST_NAME,FIRST_NAME" }
108
+ end
109
+
110
+ context "validating correct larger size" do
111
+ before { provider.larger_than = 2048 }
112
+ it { should be_nil }
113
+ end
114
+
66
115
  end
67
116
 
117
+ context "with a found message since time" do
118
+ let(:rfc_email) { File.read fixture_path('email/csv_attachment.eml') }
119
+ before {
120
+ provider.since = Time.new(2014, 1, 31)
121
+ mock_imap_search ["SINCE", "31-JAN-2014"] => [1]
122
+ mock_imap_fetch 1 => rfc_email
123
+ }
124
+ it { should match "LAST_NAME,FIRST_NAME" }
125
+
126
+ context "without ActiveSupport" do
127
+ before { allow_any_instance_of(DateTime).to receive(:respond_to?).with(:getutc) { false } }
128
+ it { should match "LAST_NAME,FIRST_NAME" }
129
+ end
130
+ end
131
+
132
+ def mock_imap_search(searches)
133
+ searches.each do |search_keys, found_keys|
134
+ sort_args = ['DATE'], search_keys, 'UTF-8'
135
+ expect(imap).to receive(:sort).with(*sort_args).and_return found_keys
136
+ end
137
+ end
138
+
139
+ def mock_imap_fetch(list)
140
+ list.each do |key, email|
141
+ expect(imap).to receive(:fetch).with(key, 'RFC822').and_return [
142
+ double("Net::IMAP::FetchData", attr: {'RFC822' => email})
143
+ ]
144
+ end
145
+ end
68
146
  end
69
147
 
70
148
  describe "#delete_data" do
@@ -74,11 +152,11 @@ module Stockboy
74
152
  expect { provider.delete_data }.to raise_error Stockboy::OutOfSequence
75
153
  end
76
154
 
77
- it "should call delete on the matching message" do
155
+ it "should call delete on the message key" do
78
156
  allow(provider).to receive(:client).and_yield(imap)
79
157
  allow(provider).to receive(:search) { [5] }
80
158
 
81
- provider.matching_message
159
+ provider.message_key
82
160
 
83
161
  expect(imap).to receive(:uid_store).with(5, "+FLAGS", [:Deleted])
84
162
  expect(imap).to receive(:expunge)
@@ -69,7 +69,7 @@ module Stockboy
69
69
 
70
70
  describe "#data" do
71
71
  let(:xml_success_fixture) do
72
- File.read(RSpec.configuration.fixture_path.join "soap/get_list/success.xml")
72
+ File.read(fixture_path "soap/get_list/success.xml")
73
73
  end
74
74
 
75
75
  let(:provider) do
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'stockboy/reader'
3
+
4
+ class BookReader < Stockboy::Reader
5
+ def parse(data)
6
+ data
7
+ end
8
+ end
9
+
10
+ class BathroomReader < Stockboy::Reader
11
+ end
12
+
13
+ module Stockboy
14
+ describe Reader do
15
+
16
+ describe "#initialize" do
17
+ subject(:reader) { BookReader.new(encoding: 'ISO-8859-1') }
18
+ its(:encoding) { should == 'ISO-8859-1' }
19
+ end
20
+
21
+ it "warns of a missing subclass implementation" do
22
+ expect { BathroomReader.new.parse(double) }.to raise_error NoMethodError
23
+ end
24
+
25
+ end
26
+ end
@@ -43,7 +43,7 @@ module Stockboy
43
43
  end
44
44
 
45
45
  describe "#parse" do
46
- let(:content) { File.read(RSpec.configuration.fixture_path.join(fixture_file)) }
46
+ let(:content) { File.read(fixture_path fixture_file) }
47
47
 
48
48
  context "with an XLS file" do
49
49
  let(:fixture_file) { 'spreadsheets/test_data.xls' }
@@ -42,7 +42,7 @@ module Stockboy
42
42
 
43
43
  describe "#parse" do
44
44
 
45
- let(:xml_file) { RSpec.configuration.fixture_path.join "xml/body.xml" }
45
+ let(:xml_file) { fixture_path "xml/body.xml" }
46
46
  let(:xml_string) { File.read(xml_file) }
47
47
  let(:elements) { ['MultiNamespacedEntryResponse', 'history', 'case'] }
48
48
  let(:output_keys) { ['logTime', 'logType', 'logText'] }
@@ -41,6 +41,31 @@ module Stockboy
41
41
  end
42
42
  end
43
43
 
44
+ describe ".translator_for" do
45
+ it "returns a translator for a registered proc" do
46
+ Translations.register :test, ->(i){ i.message.upcase }
47
+ tr = Translations.translator_for(:message, :test)
48
+ tr.call(double message: "no!").should == "NO!"
49
+ end
50
+
51
+ it "returns a translator for a registered class" do
52
+ Translations.register :test, Translations::Integer
53
+ tr = Translations.translator_for :id, :test
54
+ tr.call(double id: "42").should == 42
55
+ end
56
+
57
+ it "returns a translator for a registered instance" do
58
+ Translations.register :test, Translations::Integer.new(:id)
59
+ tr = Translations.translator_for :anything, :test
60
+ tr.call(double id: "42").should == 42
61
+ end
62
+
63
+ it "returns a no-op for unrecognized translators" do
64
+ tr = Translations.translator_for :id, :fail
65
+ tr.call(double id: "42").should == "42"
66
+ end
67
+ end
68
+
44
69
  describe ".find" do
45
70
  it "returns a callable translator" do
46
71
  callable = ->(i){ i.upcase }
metadata CHANGED
@@ -1,111 +1,111 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stockboy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Vit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-21 00:00:00.000000000 Z
11
+ date: 2014-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: roo
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: 1.12.2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.12.2
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: savon
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: 2.3.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: 2.3.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: httpi
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: mail
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: activesupport
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '3.0'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '3.0'
111
111
  description: Supports importing data over various transports with key-value remapping
@@ -116,10 +116,10 @@ executables: []
116
116
  extensions: []
117
117
  extra_rdoc_files: []
118
118
  files:
119
- - .gitignore
120
- - .rspec
121
- - .travis.yml
122
- - .yardopts
119
+ - ".gitignore"
120
+ - ".rspec"
121
+ - ".travis.yml"
122
+ - ".yardopts"
123
123
  - CHANGELOG.md
124
124
  - Gemfile
125
125
  - Guardfile
@@ -177,6 +177,7 @@ files:
177
177
  - lib/stockboy/translator.rb
178
178
  - lib/stockboy/version.rb
179
179
  - spec/fixtures/.gitkeep
180
+ - spec/fixtures/email/csv_attachment.eml
180
181
  - spec/fixtures/files/a_garbage.csv
181
182
  - spec/fixtures/files/test_data-20120101.csv
182
183
  - spec/fixtures/files/test_data-20120202.csv
@@ -208,6 +209,7 @@ files:
208
209
  - spec/stockboy/providers/imap_spec.rb
209
210
  - spec/stockboy/providers/soap_spec.rb
210
211
  - spec/stockboy/providers_spec.rb
212
+ - spec/stockboy/reader_spec.rb
211
213
  - spec/stockboy/readers/csv_spec.rb
212
214
  - spec/stockboy/readers/fixed_width_spec.rb
213
215
  - spec/stockboy/readers/spreadsheet_spec.rb
@@ -241,22 +243,23 @@ require_paths:
241
243
  - lib
242
244
  required_ruby_version: !ruby/object:Gem::Requirement
243
245
  requirements:
244
- - - '>='
246
+ - - ">="
245
247
  - !ruby/object:Gem::Version
246
248
  version: '0'
247
249
  required_rubygems_version: !ruby/object:Gem::Requirement
248
250
  requirements:
249
- - - '>='
251
+ - - ">="
250
252
  - !ruby/object:Gem::Version
251
253
  version: '0'
252
254
  requirements: []
253
255
  rubyforge_project: stockboy
254
- rubygems_version: 2.2.1
256
+ rubygems_version: 2.2.2
255
257
  signing_key:
256
258
  specification_version: 4
257
259
  summary: Multi-source data normalization library
258
260
  test_files:
259
261
  - spec/fixtures/.gitkeep
262
+ - spec/fixtures/email/csv_attachment.eml
260
263
  - spec/fixtures/files/a_garbage.csv
261
264
  - spec/fixtures/files/test_data-20120101.csv
262
265
  - spec/fixtures/files/test_data-20120202.csv
@@ -288,6 +291,7 @@ test_files:
288
291
  - spec/stockboy/providers/imap_spec.rb
289
292
  - spec/stockboy/providers/soap_spec.rb
290
293
  - spec/stockboy/providers_spec.rb
294
+ - spec/stockboy/reader_spec.rb
291
295
  - spec/stockboy/readers/csv_spec.rb
292
296
  - spec/stockboy/readers/fixed_width_spec.rb
293
297
  - spec/stockboy/readers/spreadsheet_spec.rb