stockboy 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,31 @@
1
1
  require 'spec_helper'
2
2
  require 'stockboy/job'
3
3
 
4
+ class TestProvider
5
+ attr_reader :data, :errors
6
+ def initialize(opts)
7
+ @data = opts[:data] || ""
8
+ @errors = opts[:errors] || []
9
+ end
10
+ def clear
11
+ @data = nil
12
+ end
13
+ end
14
+
15
+ class TestReader
16
+ def initialize(opts)
17
+ @parse = opts[:parse] || []
18
+ end
19
+ def parse(data)
20
+ @parse
21
+ end
22
+ end
23
+
4
24
  module Stockboy
5
25
  describe Job do
6
26
  let(:jobs_path) { RSpec.configuration.fixture_path.join('jobs') }
7
- let(:provider_stub) { double(:ftp).as_null_object }
8
- let(:reader_stub) { double(:csv).as_null_object }
27
+ let(:provider) { provider_double }
28
+ let(:reader) { reader_double }
9
29
 
10
30
  let(:job_template) {
11
31
  <<-END.gsub(/^ {6}/,'')
@@ -35,8 +55,8 @@ module Stockboy
35
55
  before do
36
56
  Stockboy.configuration.template_load_paths = [jobs_path]
37
57
 
38
- allow(Stockboy::Providers).to receive(:find) { provider_stub }
39
- allow(Stockboy::Readers).to receive(:find) { reader_stub }
58
+ allow(Stockboy::Providers).to receive(:find) { TestProvider }
59
+ allow(Stockboy::Readers).to receive(:find) { TestReader }
40
60
  end
41
61
 
42
62
  its(:filters) { should be_a Hash }
@@ -65,16 +85,19 @@ module Stockboy
65
85
  end
66
86
 
67
87
  it "assigns a registered provider from a symbol" do
88
+ Stockboy::Providers.should_receive(:find)
89
+ .with(:ftp)
90
+ .and_return(TestProvider)
68
91
  job = Job.define("test_job")
69
- job.provider.should == provider_stub
92
+ job.provider.should be_a TestProvider
70
93
  end
71
94
 
72
95
  it "assigns a registered reader from a symbol" do
73
96
  Stockboy::Readers.should_receive(:find)
74
97
  .with(:csv)
75
- .and_return(reader_stub)
98
+ .and_return(TestReader)
76
99
  job = Job.define("test_job")
77
- job.reader.should == reader_stub
100
+ job.reader.should be_a TestReader
78
101
  end
79
102
 
80
103
  it "assigns attributes from a block" do
@@ -93,12 +116,11 @@ module Stockboy
93
116
  let(:attribute_map) { AttributeMap.new { name } }
94
117
 
95
118
  subject(:job) do
96
- Job.new(provider: double(:provider, data:"", errors:[]),
97
- attributes: attribute_map)
119
+ Job.new(provider: provider, attributes: attribute_map)
98
120
  end
99
121
 
100
122
  it "records total received record count" do
101
- job.reader = double(parse: [{"name"=>"A"},{"name"=>"B"}])
123
+ job.reader = reader_double(parse: [{"name"=>"A"},{"name"=>"B"}])
102
124
 
103
125
  job.process
104
126
  job.total_records.should == 2
@@ -155,8 +177,7 @@ module Stockboy
155
177
  let(:attribute_map) { AttributeMap.new { name } }
156
178
 
157
179
  subject(:job) do
158
- Job.new(provider: double(:provider, data:"", errors:[]),
159
- attributes: attribute_map)
180
+ Job.new(provider: provider, attributes: attribute_map)
160
181
  end
161
182
 
162
183
  context "before processing" do
@@ -180,9 +201,7 @@ module Stockboy
180
201
 
181
202
  describe "#processed?" do
182
203
  subject(:job) do
183
- Job.new(provider: provider_stub,
184
- reader: reader_stub,
185
- attributes: AttributeMap.new)
204
+ Job.new(provider: provider, reader: reader, attributes: AttributeMap.new)
186
205
  end
187
206
 
188
207
  it "indicates if the job has been processed" do
@@ -194,11 +213,9 @@ module Stockboy
194
213
 
195
214
  describe "#trigger" do
196
215
 
197
- let(:provider_stub) { double(delete_data: true) }
198
-
199
216
  subject(:job) do
200
217
  Job.new(
201
- provider: provider_stub,
218
+ provider: provider,
202
219
  triggers: {
203
220
  success: [proc { |j| j.provider.delete_data },
204
221
  proc { |j, stats| stats[:count] = 1 if stats }]
@@ -207,11 +224,12 @@ module Stockboy
207
224
  end
208
225
 
209
226
  it "should yield itself to each trigger" do
210
- provider_stub.should_receive(:delete_data).once
227
+ expect(job.provider).to receive(:delete_data).once
211
228
  job.trigger(:success)
212
229
  end
213
230
 
214
231
  it "should yield args to each trigger" do
232
+ expect(job.provider).to receive(:delete_data).once
215
233
  stats = {}
216
234
  job.trigger(:success, stats)
217
235
  stats[:count].should == 1
@@ -234,5 +252,12 @@ module Stockboy
234
252
 
235
253
  end
236
254
 
255
+ def provider_double(opts={})
256
+ TestProvider.new(opts)
257
+ end
258
+
259
+ def reader_double(opts={})
260
+ TestReader.new(opts)
261
+ end
237
262
  end
238
263
  end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+ require 'stockboy/provider_repeater'
3
+
4
+ class PaginatedProviderSubclass < Stockboy::Provider
5
+ attr_accessor :page
6
+ def validate
7
+ true
8
+ end
9
+ def fetch_data
10
+ @data = "TEST,DATA,#{page}"
11
+ end
12
+ end
13
+
14
+ module Stockboy
15
+ describe ProviderRepeater do
16
+
17
+ let(:provider) { PaginatedProviderSubclass.new }
18
+
19
+ describe "#data" do
20
+ let(:repeater) {
21
+ ProviderRepeater.new(provider) do |output, provider|
22
+ 1.upto 3 do |i|
23
+ provider.page = i
24
+ output << provider
25
+ end
26
+ end
27
+ }
28
+
29
+ it "yields each data set" do
30
+ calls = []
31
+ repeater.data { |data| calls << data[-1] }
32
+ calls.should == ["1", "2", "3"]
33
+ end
34
+
35
+ end
36
+
37
+ describe "#each" do
38
+
39
+ context "without a block" do
40
+ let(:repeater) { ProviderRepeater.new(provider) }
41
+
42
+ it "yields the provider once" do
43
+ provider.page = 42
44
+ calls = []
45
+ repeater.each do |nth_provider|
46
+ calls << nth_provider
47
+ end
48
+ calls.map(&:page).should == [42]
49
+ end
50
+ end
51
+
52
+ context "when it passes a non-provider" do
53
+ let(:repeater) {
54
+ ProviderRepeater.new(provider) do |output, provider|
55
+ output << nil
56
+ end
57
+ }
58
+
59
+ it "should raise a helpful error" do
60
+ expect { repeater.each { |provider| } }.to raise_error(
61
+ "expected Provider, got NilClass" )
62
+ end
63
+ end
64
+
65
+ context "when it is defined with yield" do
66
+ let(:repeater) {
67
+ ProviderRepeater.new(provider) do |output, provider|
68
+ yield provider
69
+ end
70
+ }
71
+
72
+ it "should raise a helpful error" do
73
+ expect { repeater.data { |data| } }.to raise_error(
74
+ "use output << provider instead of yield" )
75
+ end
76
+ end
77
+ end
78
+
79
+ end
80
+ end
@@ -2,9 +2,11 @@ require 'spec_helper'
2
2
  require 'stockboy/provider'
3
3
 
4
4
  class ProviderSubclass < Stockboy::Provider
5
- attr_accessor :foo
6
5
  def validate
7
- errors.add_on_empty(:foo, "Foo is empty")
6
+ true
7
+ end
8
+ def fetch_data
9
+ @data = "TEST,DATA"
8
10
  end
9
11
  end
10
12
 
@@ -30,5 +32,23 @@ module Stockboy
30
32
  expect{ subject.send :fetch_data }.to raise_error(NoMethodError)
31
33
  end
32
34
  end
35
+
36
+ describe "#data" do
37
+ subject(:provider) { ProviderSubclass.new(foo: true) }
38
+
39
+ it "fetches data when there is none" do
40
+ expect(provider).to receive(:fetch_data).once.and_call_original
41
+ 2.times do
42
+ provider.data.should == "TEST,DATA"
43
+ end
44
+ end
45
+
46
+ it "yields data to a block" do
47
+ provider.data do |data|
48
+ data.should == "TEST,DATA"
49
+ end
50
+ end
51
+ end
52
+
33
53
  end
34
54
  end
@@ -23,7 +23,7 @@ module Stockboy
23
23
 
24
24
  describe ".new" do
25
25
  it "has no errors" do
26
- provider.errors.messages.should be_empty
26
+ provider.errors.should be_empty
27
27
  end
28
28
 
29
29
  it "accepts block initialization" do
@@ -55,8 +55,8 @@ module Stockboy
55
55
  it "fails with an error if the file doesn't exist" do
56
56
  provider.file_name = "missing-file.csv"
57
57
  provider.data.should be_nil
58
- provider.valid?.should == false
59
- provider.errors[:base].should_not be_empty
58
+ provider.valid?.should be_false
59
+ provider.errors.first.should match /not found/
60
60
  end
61
61
 
62
62
  it "finds last matching file from string glob" do
@@ -76,16 +76,16 @@ module Stockboy
76
76
  end
77
77
 
78
78
  context "with :since validation" do
79
- let(:recently) { Time.now - 60 }
79
+ let(:recently) { Time.now - 60 }
80
+ let(:last_week) { Time.now - 86400 }
80
81
 
81
82
  it "skips old files" do
82
- expect_any_instance_of(::File).to receive(:mtime).and_return Time.now - 86400
83
- provider.file_dir = RSpec.configuration.fixture_path.join("files")
83
+ expect_any_instance_of(::File).to receive(:mtime).and_return last_week
84
84
  provider.file_name = '*.csv'
85
85
  provider.since = recently
86
86
 
87
87
  provider.data.should be_nil
88
- provider.errors[:response].should include "No new files since #{recently}"
88
+ provider.errors.first.should == "no new files since #{recently}"
89
89
  end
90
90
  end
91
91
  end
@@ -32,7 +32,7 @@ module Stockboy
32
32
 
33
33
  describe ".new" do
34
34
  it "has no errors" do
35
- subject.errors.messages.should be_empty
35
+ subject.errors.should be_empty
36
36
  end
37
37
 
38
38
  it "accepts block initialization" do
@@ -67,14 +67,14 @@ module Stockboy
67
67
  provider.host = nil
68
68
  provider.data
69
69
 
70
- provider.errors.include?(:host).should be_true
70
+ provider.errors.first.should match /host/
71
71
  end
72
72
 
73
73
  it "adds an error on missing file_name" do
74
74
  provider.file_name = nil
75
75
  provider.data
76
76
 
77
- provider.errors.include?(:file_name).should be_true
77
+ provider.errors.first.should match /file_name/
78
78
  end
79
79
 
80
80
  it "downloads the last matching file" do
@@ -58,15 +58,17 @@ module Stockboy
58
58
 
59
59
  describe "validation" do
60
60
  it "should not be valid without a method" do
61
+ provider.uri = "http://example.com"
61
62
  provider.method = nil
62
63
  provider.should_not be_valid
63
- provider.errors.keys.should include(:method)
64
+ provider.errors.first.should match /method/
64
65
  end
65
66
 
66
67
  it "should not be valid without a uri" do
67
68
  provider.uri = ""
69
+ provider.method = :get
68
70
  provider.should_not be_valid
69
- provider.errors.keys.should include(:uri)
71
+ provider.errors.first.should match /uri/
70
72
  end
71
73
  end
72
74
 
@@ -39,7 +39,7 @@ module Stockboy
39
39
 
40
40
  describe ".new" do
41
41
  it "has no errors" do
42
- provider.errors.messages.should be_empty
42
+ provider.errors.should be_empty
43
43
  end
44
44
 
45
45
  it "accepts block initialization" do
@@ -108,7 +108,7 @@ module Stockboy
108
108
  it "closes connections when catching exceptions" do
109
109
  net_imap = expect_connection("hhh", "uuu", "ppp", "UNBOX")
110
110
  provider.client { |i| raise Net::IMAP::Error }
111
- provider.errors[:response].should include "IMAP connection error"
111
+ provider.errors.first.should match /IMAP connection error/
112
112
  end
113
113
 
114
114
  end
@@ -52,7 +52,7 @@ module Stockboy
52
52
  context "without a WSDL document" do
53
53
  it "has error for blank endpoint & WSDL namespace" do
54
54
  provider.valid?
55
- provider.errors.keys.should include(:endpoint)
55
+ provider.errors.first.should match /endpoint/
56
56
  end
57
57
  end
58
58
  end
@@ -88,10 +88,15 @@ module Stockboy
88
88
  provider.data
89
89
  end
90
90
 
91
- it "returns hash data on success" do
91
+ it "returns hash data on success by default" do
92
92
  should be_a Hash
93
93
  end
94
94
 
95
+ it "returns xml data on success with an xml response_format" do
96
+ provider.response_format = :xml
97
+ should be_a String
98
+ end
99
+
95
100
  it "uses string keys" do
96
101
  response.keys.each { |k| k.should be_a String }
97
102
  end
data/stockboy.gemspec CHANGED
@@ -29,5 +29,5 @@ Gem::Specification.new do |s|
29
29
  s.add_runtime_dependency "savon", ">= 2.3.0"
30
30
  s.add_runtime_dependency "httpi"
31
31
  s.add_runtime_dependency "mail"
32
- s.add_runtime_dependency "activemodel", ">= 3.0"
32
+ s.add_runtime_dependency "activesupport", ">= 3.0"
33
33
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stockboy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
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-02-07 00:00:00.000000000 Z
11
+ date: 2014-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: activemodel
98
+ name: activesupport
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - '>='
@@ -141,6 +141,7 @@ files:
141
141
  - lib/stockboy/job.rb
142
142
  - lib/stockboy/mapped_record.rb
143
143
  - lib/stockboy/provider.rb
144
+ - lib/stockboy/provider_repeater.rb
144
145
  - lib/stockboy/providers.rb
145
146
  - lib/stockboy/providers/file.rb
146
147
  - lib/stockboy/providers/ftp.rb
@@ -198,6 +199,7 @@ files:
198
199
  - spec/stockboy/filters_spec.rb
199
200
  - spec/stockboy/job_spec.rb
200
201
  - spec/stockboy/mapped_record_spec.rb
202
+ - spec/stockboy/provider_repeater_spec.rb
201
203
  - spec/stockboy/provider_spec.rb
202
204
  - spec/stockboy/providers/file_spec.rb
203
205
  - spec/stockboy/providers/ftp_spec.rb
@@ -277,6 +279,7 @@ test_files:
277
279
  - spec/stockboy/filters_spec.rb
278
280
  - spec/stockboy/job_spec.rb
279
281
  - spec/stockboy/mapped_record_spec.rb
282
+ - spec/stockboy/provider_repeater_spec.rb
280
283
  - spec/stockboy/provider_spec.rb
281
284
  - spec/stockboy/providers/file_spec.rb
282
285
  - spec/stockboy/providers/ftp_spec.rb