stockboy 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/stockboy/providers/soap.rb +2 -0
- data/lib/stockboy/version.rb +1 -1
- data/spec/stockboy/attribute_map_spec.rb +10 -10
- data/spec/stockboy/attribute_spec.rb +7 -7
- data/spec/stockboy/candidate_record_spec.rb +18 -18
- data/spec/stockboy/configuration_spec.rb +4 -4
- data/spec/stockboy/configurator_spec.rb +24 -24
- data/spec/stockboy/filter_chain_spec.rb +4 -4
- data/spec/stockboy/filter_spec.rb +4 -4
- data/spec/stockboy/filters/missing_email_spec.rb +4 -4
- data/spec/stockboy/filters_spec.rb +4 -4
- data/spec/stockboy/job_spec.rb +24 -24
- data/spec/stockboy/mapped_record_spec.rb +5 -4
- data/spec/stockboy/provider_repeater_spec.rb +2 -2
- data/spec/stockboy/provider_spec.rb +3 -3
- data/spec/stockboy/providers/file_spec.rb +20 -20
- data/spec/stockboy/providers/ftp_spec.rb +20 -20
- data/spec/stockboy/providers/http_spec.rb +28 -28
- data/spec/stockboy/providers/imap/search_options_spec.rb +11 -11
- data/spec/stockboy/providers/imap_spec.rb +23 -23
- data/spec/stockboy/providers/soap_spec.rb +17 -17
- data/spec/stockboy/providers_spec.rb +4 -4
- data/spec/stockboy/readers/csv_spec.rb +13 -9
- data/spec/stockboy/readers/fixed_width_spec.rb +6 -6
- data/spec/stockboy/readers/json_spec.rb +1 -1
- data/spec/stockboy/readers/spreadsheet_spec.rb +15 -15
- data/spec/stockboy/readers/xml_spec.rb +12 -12
- data/spec/stockboy/readers_spec.rb +3 -3
- data/spec/stockboy/source_record_spec.rb +2 -2
- data/spec/stockboy/template_file_spec.rb +3 -3
- data/spec/stockboy/translations/boolean_spec.rb +1 -1
- data/spec/stockboy/translations/date_spec.rb +5 -5
- data/spec/stockboy/translations/decimal_spec.rb +3 -3
- data/spec/stockboy/translations/default_empty_string_spec.rb +4 -4
- data/spec/stockboy/translations/default_false_spec.rb +1 -1
- data/spec/stockboy/translations/default_nil_spec.rb +4 -4
- data/spec/stockboy/translations/default_true_spec.rb +1 -1
- data/spec/stockboy/translations/default_zero_spec.rb +4 -4
- data/spec/stockboy/translations/integer_spec.rb +2 -2
- data/spec/stockboy/translations/string_spec.rb +2 -2
- data/spec/stockboy/translations/time_spec.rb +3 -3
- data/spec/stockboy/translations/uk_date_spec.rb +5 -5
- data/spec/stockboy/translations/us_date_spec.rb +5 -5
- data/spec/stockboy/translations_spec.rb +9 -9
- data/spec/stockboy/translator_spec.rb +2 -2
- data/stockboy.gemspec +1 -1
- metadata +4 -4
@@ -9,8 +9,8 @@ module Stockboy
|
|
9
9
|
|
10
10
|
it "initializes keys and values from a hash" do
|
11
11
|
chain = FilterChain.new(no_angels: filter1, no_daleks: filter2)
|
12
|
-
chain.keys.
|
13
|
-
chain.values.
|
12
|
+
expect(chain.keys).to eq [:no_angels, :no_daleks]
|
13
|
+
expect(chain.values).to eq [filter1, filter2]
|
14
14
|
end
|
15
15
|
|
16
16
|
describe "#reset" do
|
@@ -23,7 +23,7 @@ module Stockboy
|
|
23
23
|
|
24
24
|
it "returns a hash of filter keys to empty arrays" do
|
25
25
|
empty_records = chain.reset
|
26
|
-
empty_records.
|
26
|
+
expect(empty_records).to eq({no_angels: [], no_daleks: []})
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -31,7 +31,7 @@ module Stockboy
|
|
31
31
|
it "adds filters to the front of the chain" do
|
32
32
|
chain = FilterChain.new(filter1: double)
|
33
33
|
chain.prepend(filter0: double)
|
34
|
-
chain.keys.
|
34
|
+
expect(chain.keys).to eq [:filter0, :filter1]
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
@@ -21,21 +21,21 @@ module Stockboy
|
|
21
21
|
|
22
22
|
context "matching raw value" do
|
23
23
|
it "returns true for match" do
|
24
|
-
filter.call(double(species:"babylichtus"), empty_values).
|
24
|
+
expect(filter.call(double(species:"babylichtus"), empty_values)).to be true
|
25
25
|
end
|
26
26
|
|
27
27
|
it "returns false for no match" do
|
28
|
-
filter.call(double(species:"triceratops"), empty_values).
|
28
|
+
expect(filter.call(double(species:"triceratops"), empty_values)).to be false
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
context "matching translated value" do
|
33
33
|
it "returns true for match" do
|
34
|
-
filter.call(empty_values, double(species:"babelfish")).
|
34
|
+
expect(filter.call(empty_values, double(species:"babelfish"))).to be true
|
35
35
|
end
|
36
36
|
|
37
37
|
it "returns false for no match" do
|
38
|
-
filter.call(empty_values, double(species:"rhinoceros")).
|
38
|
+
expect(filter.call(empty_values, double(species:"rhinoceros"))).to be false
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -5,22 +5,22 @@ describe Stockboy::Filters::MissingEmail do
|
|
5
5
|
subject(:filter) { described_class.new(:e) }
|
6
6
|
it 'allows email addresses' do
|
7
7
|
record = OpenStruct.new(e: 'me@example.com')
|
8
|
-
filter.call(record, record).
|
8
|
+
expect(filter.call(record, record)).to be false
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'catches empty strings' do
|
12
12
|
record = OpenStruct.new(e: '')
|
13
|
-
filter.call(record, record).
|
13
|
+
expect(filter.call(record, record)).to be true
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'catches hyphen placeholders' do
|
17
17
|
record = OpenStruct.new(e: '-')
|
18
|
-
filter.call(record, record).
|
18
|
+
expect(filter.call(record, record)).to be true
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'uses translated output value' do
|
22
22
|
input = OpenStruct.new(e: '', other: 'me@example.com')
|
23
23
|
output = OpenStruct.new(e: input.other)
|
24
|
-
filter.call(input, output).
|
24
|
+
expect(filter.call(input, output)).to be false
|
25
25
|
end
|
26
26
|
end
|
@@ -8,21 +8,21 @@ module Stockboy
|
|
8
8
|
|
9
9
|
describe ".register" do
|
10
10
|
it "registers a key and class" do
|
11
|
-
Filters.register(:invalid, filter).
|
11
|
+
expect(Filters.register(:invalid, filter)).to be === filter
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
describe ".find" do
|
16
16
|
it "returns a filter class" do
|
17
17
|
Filters.register(:invalid, filter)
|
18
|
-
Filters.find(:invalid).
|
18
|
+
expect(Filters.find(:invalid)).to be === filter
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
describe ".[]" do
|
23
23
|
it "returns a filter class" do
|
24
24
|
Filters.register(:invalid, filter)
|
25
|
-
Filters[:invalid].
|
25
|
+
expect(Filters[:invalid]).to be === filter
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -30,7 +30,7 @@ module Stockboy
|
|
30
30
|
it "returns all registered filters" do
|
31
31
|
Filters.register(:invalid, filter)
|
32
32
|
Filters.register(:semivalid, filter)
|
33
|
-
Filters.all.
|
33
|
+
expect(Filters.all).to include(invalid: filter, semivalid: filter)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
data/spec/stockboy/job_spec.rb
CHANGED
@@ -74,14 +74,14 @@ module Stockboy
|
|
74
74
|
end
|
75
75
|
|
76
76
|
it "returns an instance of Job" do
|
77
|
-
Job.define("test_job").
|
77
|
+
expect(Job.define("test_job")).to be_a Job
|
78
78
|
end
|
79
79
|
|
80
80
|
it "yields the defined job" do
|
81
81
|
yielded = nil
|
82
82
|
job = Job.define("test_job") { |j| yielded = j }
|
83
|
-
job.
|
84
|
-
job.
|
83
|
+
expect(job).to be_a Job
|
84
|
+
expect(job).to be yielded
|
85
85
|
end
|
86
86
|
|
87
87
|
it "should read a file from a path" do
|
@@ -94,7 +94,7 @@ module Stockboy
|
|
94
94
|
.with(:ftp)
|
95
95
|
.and_return(TestProvider)
|
96
96
|
job = Job.define("test_job")
|
97
|
-
job.provider.
|
97
|
+
expect(job.provider).to be_a TestProvider
|
98
98
|
end
|
99
99
|
|
100
100
|
it "assigns a registered reader from a symbol" do
|
@@ -102,18 +102,18 @@ module Stockboy
|
|
102
102
|
.with(:csv)
|
103
103
|
.and_return(TestReader)
|
104
104
|
job = Job.define("test_job")
|
105
|
-
job.reader.
|
105
|
+
expect(job.reader).to be_a TestReader
|
106
106
|
end
|
107
107
|
|
108
108
|
it "assigns attributes from a block" do
|
109
109
|
job = Job.define("test_job")
|
110
|
-
job.attributes.map(&:to).
|
110
|
+
expect(job.attributes.map(&:to)).to eq [:name, :email, :updated_at]
|
111
111
|
end
|
112
112
|
|
113
113
|
it "assigns triggers into their associated array from a block" do
|
114
114
|
job = Job.define("test_job")
|
115
|
-
job.triggers[:cleanup].size.
|
116
|
-
job.triggers[:cleanup].each { |t| t.
|
115
|
+
expect(job.triggers[:cleanup].size).to eq 2
|
116
|
+
job.triggers[:cleanup].each { |t| expect(t).to be_a Proc }
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
@@ -126,12 +126,12 @@ module Stockboy
|
|
126
126
|
|
127
127
|
it "replaces the attribute map" do
|
128
128
|
job.attributes = AttributeMap.new do last_name end
|
129
|
-
job.attributes.map(&:to).
|
129
|
+
expect(job.attributes.map(&:to)).to eq [:last_name]
|
130
130
|
end
|
131
131
|
|
132
132
|
it "resets the job" do
|
133
133
|
job.attributes = AttributeMap.new do last_name end
|
134
|
-
job.all_records.
|
134
|
+
expect(job.all_records).to be_empty
|
135
135
|
end
|
136
136
|
|
137
137
|
end
|
@@ -147,7 +147,7 @@ module Stockboy
|
|
147
147
|
job.reader = reader_double(parse: [{"name"=>"A"},{"name"=>"B"}])
|
148
148
|
|
149
149
|
job.process
|
150
|
-
job.total_records.
|
150
|
+
expect(job.total_records).to eq 2
|
151
151
|
end
|
152
152
|
|
153
153
|
it "partitions records by filter" do
|
@@ -155,7 +155,7 @@ module Stockboy
|
|
155
155
|
job.filters = {alpha: proc{ |r| r.name =~ /A/ }}
|
156
156
|
|
157
157
|
job.process
|
158
|
-
job.records[:alpha].length.
|
158
|
+
expect(job.records[:alpha].length).to eq 1
|
159
159
|
end
|
160
160
|
|
161
161
|
it "keeps unfiltered_records" do
|
@@ -163,7 +163,7 @@ module Stockboy
|
|
163
163
|
job.filters = {zeta: proc{ |r| r.name =~ /Z/ }}
|
164
164
|
|
165
165
|
job.process
|
166
|
-
job.unfiltered_records.length.
|
166
|
+
expect(job.unfiltered_records.length).to eq 1
|
167
167
|
end
|
168
168
|
|
169
169
|
it "keeps all_records" do
|
@@ -171,7 +171,7 @@ module Stockboy
|
|
171
171
|
job.filters = {alpha: proc{ |r| r.name =~ /A/ }}
|
172
172
|
|
173
173
|
job.process
|
174
|
-
job.all_records.length.
|
174
|
+
expect(job.all_records.length).to eq 2
|
175
175
|
end
|
176
176
|
|
177
177
|
it "resets filters between runs" do
|
@@ -186,14 +186,14 @@ module Stockboy
|
|
186
186
|
job.reader = double(parse: [{"name"=>"A"},{"name"=>"Z"}])
|
187
187
|
job.filters = {alpha: counter = CountingFilter.new(/A/)}
|
188
188
|
|
189
|
-
counter.matches.
|
189
|
+
expect(counter.matches).to eq 0
|
190
190
|
2.times { job.process }
|
191
|
-
counter.matches.
|
191
|
+
expect(counter.matches).to eq 1
|
192
192
|
end
|
193
193
|
|
194
194
|
it "has empty partitions" do
|
195
195
|
job.filters = {alpha: proc{ |r| r.name =~ /A/ }, beta: proc{ |r| r.name =~ /B/ }}
|
196
|
-
job.records.
|
196
|
+
expect(job.records).to eq({alpha: [], beta: []})
|
197
197
|
end
|
198
198
|
|
199
199
|
context "with a repeating provider" do
|
@@ -209,7 +209,7 @@ module Stockboy
|
|
209
209
|
|
210
210
|
it "it loads all records into a set" do
|
211
211
|
job.process
|
212
|
-
job.all_records.size.
|
212
|
+
expect(job.all_records.size).to eq 3
|
213
213
|
end
|
214
214
|
end
|
215
215
|
|
@@ -224,7 +224,7 @@ module Stockboy
|
|
224
224
|
|
225
225
|
context "before processing" do
|
226
226
|
it "should be empty" do
|
227
|
-
job.record_counts.
|
227
|
+
expect(job.record_counts).to eq({})
|
228
228
|
end
|
229
229
|
end
|
230
230
|
|
@@ -237,7 +237,7 @@ module Stockboy
|
|
237
237
|
job.reader = double(parse: [{"name"=>"Arthur"}, {"name"=>"Abc"}, {"name"=>"Zaphod"}])
|
238
238
|
job.process
|
239
239
|
|
240
|
-
job.record_counts.
|
240
|
+
expect(job.record_counts).to eq({alpha: 2, zeta: 1})
|
241
241
|
end
|
242
242
|
end
|
243
243
|
|
@@ -247,9 +247,9 @@ module Stockboy
|
|
247
247
|
end
|
248
248
|
|
249
249
|
it "indicates if the job has been processed" do
|
250
|
-
job.processed
|
250
|
+
expect(job.processed?).to be false
|
251
251
|
job.process
|
252
|
-
job.processed
|
252
|
+
expect(job.processed?).to be true
|
253
253
|
end
|
254
254
|
end
|
255
255
|
|
@@ -274,7 +274,7 @@ module Stockboy
|
|
274
274
|
expect(job.provider).to receive(:delete_data).once
|
275
275
|
stats = {}
|
276
276
|
job.trigger(:success, stats)
|
277
|
-
stats[:count].
|
277
|
+
expect(stats[:count]).to eq 1
|
278
278
|
end
|
279
279
|
|
280
280
|
end
|
@@ -284,7 +284,7 @@ module Stockboy
|
|
284
284
|
it "replaces existing triggers" do
|
285
285
|
job.triggers = {breakfast: double}
|
286
286
|
job.triggers = {lunch: double}
|
287
|
-
job.triggers.keys.
|
287
|
+
expect(job.triggers.keys).to eq [:lunch]
|
288
288
|
end
|
289
289
|
|
290
290
|
end
|
@@ -8,23 +8,24 @@ module Stockboy
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it "accesses initialized fields from hash" do
|
11
|
-
record.full_name.
|
11
|
+
expect(record.full_name).to eq 'Arthur Dent'
|
12
12
|
end
|
13
13
|
|
14
14
|
it "does not redefine accessor methods" do
|
15
15
|
record1 = MappedRecord.new(:full_name => 'Arthur Dent')
|
16
16
|
record2 = MappedRecord.new(:full_name => 'Arthur Dent')
|
17
17
|
|
18
|
-
record1.method(:full_name).owner.
|
18
|
+
expect(record1.method(:full_name).owner).to eq(
|
19
19
|
record2.method(:full_name).owner
|
20
|
+
)
|
20
21
|
end
|
21
22
|
|
22
23
|
it "only has its own accessor methods" do
|
23
24
|
record1 = MappedRecord.new(:first_name => 'Arthur')
|
24
25
|
record2 = MappedRecord.new(:last_name => 'Dent')
|
25
26
|
|
26
|
-
record1.
|
27
|
-
record2.
|
27
|
+
expect(record1).not_to respond_to(:last_name)
|
28
|
+
expect(record2).not_to respond_to(:first_name)
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
@@ -27,7 +27,7 @@ module Stockboy
|
|
27
27
|
it "yields each data set" do
|
28
28
|
calls = []
|
29
29
|
repeater.data { |data| calls << data.split(",").last }
|
30
|
-
calls.
|
30
|
+
expect(calls).to eq ["1", "2", "3"]
|
31
31
|
end
|
32
32
|
|
33
33
|
end
|
@@ -43,7 +43,7 @@ module Stockboy
|
|
43
43
|
repeater.each do |nth_provider|
|
44
44
|
calls << nth_provider
|
45
45
|
end
|
46
|
-
calls.map(&:page).
|
46
|
+
expect(calls.map(&:page)).to eq [42]
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -41,13 +41,13 @@ module Stockboy
|
|
41
41
|
it "fetches data when there is none" do
|
42
42
|
expect(provider).to receive(:fetch_data).once.and_call_original
|
43
43
|
2.times do
|
44
|
-
provider.data.
|
44
|
+
expect(provider.data).to eq "TEST,DATA"
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
48
|
it "yields data to a block" do
|
49
49
|
provider.data do |data|
|
50
|
-
data.
|
50
|
+
expect(data).to eq "TEST,DATA"
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -58,7 +58,7 @@ module Stockboy
|
|
58
58
|
it "clears and reloads the data" do
|
59
59
|
data = provider.data
|
60
60
|
expect(provider).to receive(:fetch_data).once.and_call_original
|
61
|
-
provider.reload.
|
61
|
+
expect(provider.reload).to eq data
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
@@ -13,22 +13,22 @@ module Stockboy
|
|
13
13
|
provider.file_larger = 1024
|
14
14
|
provider.pick = :first
|
15
15
|
|
16
|
-
provider.file_dir.
|
17
|
-
provider.file_name.
|
18
|
-
provider.file_newer.
|
19
|
-
provider.file_smaller.
|
20
|
-
provider.file_larger.
|
21
|
-
provider.pick.
|
16
|
+
expect(provider.file_dir).to eq "fixtures/files"
|
17
|
+
expect(provider.file_name).to eq %r{import_20[1-9][0-9]-(0[1-9]|1[0-2])-([0-2][1-9]|3[0-1]).csv}
|
18
|
+
expect(provider.file_newer).to eq Date.today
|
19
|
+
expect(provider.file_smaller).to eq 1024**2
|
20
|
+
expect(provider.file_larger).to eq 1024
|
21
|
+
expect(provider.pick).to eq :first
|
22
22
|
end
|
23
23
|
|
24
24
|
describe ".new" do
|
25
25
|
it "has no errors" do
|
26
|
-
provider.errors.
|
26
|
+
expect(provider.errors).to be_empty
|
27
27
|
end
|
28
28
|
|
29
29
|
it "accepts block initialization" do
|
30
30
|
provider = Providers::File.new{ |f| f.file_dir 'fixtures/files' }
|
31
|
-
provider.file_dir.
|
31
|
+
expect(provider.file_dir).to eq 'fixtures/files'
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -61,25 +61,25 @@ module Stockboy
|
|
61
61
|
|
62
62
|
it "fails with an error if the file doesn't exist" do
|
63
63
|
provider.file_name = "missing-file.csv"
|
64
|
-
provider.data.
|
65
|
-
provider.valid
|
66
|
-
provider.errors.first.
|
64
|
+
expect(provider.data).to be nil
|
65
|
+
expect(provider.valid?).to be false
|
66
|
+
expect(provider.errors.first).to match /not found/
|
67
67
|
end
|
68
68
|
|
69
69
|
it "finds last matching file from string glob" do
|
70
70
|
provider.file_name = "test_data-*.csv"
|
71
|
-
provider.data.
|
71
|
+
expect(provider.data).to eq "2012-02-02\n"
|
72
72
|
end
|
73
73
|
|
74
74
|
it "finds first matching file from string glob" do
|
75
75
|
provider.file_name = "test_data-*.csv"
|
76
76
|
provider.pick = :first
|
77
|
-
provider.data.
|
77
|
+
expect(provider.data).to eq "2012-01-01\n"
|
78
78
|
end
|
79
79
|
|
80
80
|
it "finds last matching file from regex" do
|
81
81
|
provider.file_name = /test_data/
|
82
|
-
provider.data.
|
82
|
+
expect(provider.data).to eq "2012-02-02\n"
|
83
83
|
end
|
84
84
|
|
85
85
|
context "metadata validation" do
|
@@ -90,22 +90,22 @@ module Stockboy
|
|
90
90
|
it "skips old files with :since" do
|
91
91
|
expect_any_instance_of(::File).to receive(:mtime).and_return last_week
|
92
92
|
provider.since = recently
|
93
|
-
provider.data.
|
94
|
-
provider.errors.first.
|
93
|
+
expect(provider.data).to be nil
|
94
|
+
expect(provider.errors.first).to eq "no new files since #{recently}"
|
95
95
|
end
|
96
96
|
|
97
97
|
it "skips large files with :file_smaller" do
|
98
98
|
expect_any_instance_of(::File).to receive(:size).and_return 1001
|
99
99
|
provider.file_smaller = 1000
|
100
|
-
provider.data.
|
101
|
-
provider.errors.first.
|
100
|
+
expect(provider.data).to be nil
|
101
|
+
expect(provider.errors.first).to eq "file size larger than 1000"
|
102
102
|
end
|
103
103
|
|
104
104
|
it "skips small files with :file_larger" do
|
105
105
|
expect_any_instance_of(::File).to receive(:size).and_return 999
|
106
106
|
provider.file_larger = 1000
|
107
|
-
provider.data.
|
108
|
-
provider.errors.first.
|
107
|
+
expect(provider.data).to be nil
|
108
|
+
expect(provider.errors.first).to eq "file size smaller than 1000"
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|