stockboy 1.1.0 → 1.1.1
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 +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
|