stockboy 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +5 -0
  4. data/.yardopts +7 -0
  5. data/CHANGELOG.md +24 -0
  6. data/Gemfile +12 -0
  7. data/Guardfile +10 -0
  8. data/LICENSE +21 -0
  9. data/README.md +293 -0
  10. data/Rakefile +30 -0
  11. data/lib/stockboy.rb +80 -0
  12. data/lib/stockboy/attribute.rb +11 -0
  13. data/lib/stockboy/attribute_map.rb +74 -0
  14. data/lib/stockboy/candidate_record.rb +130 -0
  15. data/lib/stockboy/configuration.rb +62 -0
  16. data/lib/stockboy/configurator.rb +176 -0
  17. data/lib/stockboy/dsl.rb +68 -0
  18. data/lib/stockboy/exceptions.rb +3 -0
  19. data/lib/stockboy/filter.rb +58 -0
  20. data/lib/stockboy/filter_chain.rb +41 -0
  21. data/lib/stockboy/filters.rb +11 -0
  22. data/lib/stockboy/filters/missing_email.rb +37 -0
  23. data/lib/stockboy/job.rb +241 -0
  24. data/lib/stockboy/mapped_record.rb +59 -0
  25. data/lib/stockboy/provider.rb +238 -0
  26. data/lib/stockboy/providers.rb +11 -0
  27. data/lib/stockboy/providers/file.rb +135 -0
  28. data/lib/stockboy/providers/ftp.rb +205 -0
  29. data/lib/stockboy/providers/http.rb +123 -0
  30. data/lib/stockboy/providers/imap.rb +290 -0
  31. data/lib/stockboy/providers/soap.rb +120 -0
  32. data/lib/stockboy/railtie.rb +28 -0
  33. data/lib/stockboy/reader.rb +59 -0
  34. data/lib/stockboy/readers.rb +11 -0
  35. data/lib/stockboy/readers/csv.rb +115 -0
  36. data/lib/stockboy/readers/fixed_width.rb +121 -0
  37. data/lib/stockboy/readers/spreadsheet.rb +144 -0
  38. data/lib/stockboy/readers/xml.rb +155 -0
  39. data/lib/stockboy/registry.rb +42 -0
  40. data/lib/stockboy/source_record.rb +43 -0
  41. data/lib/stockboy/string_pool.rb +35 -0
  42. data/lib/stockboy/template_file.rb +44 -0
  43. data/lib/stockboy/translations.rb +70 -0
  44. data/lib/stockboy/translations/boolean.rb +58 -0
  45. data/lib/stockboy/translations/date.rb +41 -0
  46. data/lib/stockboy/translations/decimal.rb +33 -0
  47. data/lib/stockboy/translations/default_empty_string.rb +38 -0
  48. data/lib/stockboy/translations/default_false.rb +41 -0
  49. data/lib/stockboy/translations/default_nil.rb +38 -0
  50. data/lib/stockboy/translations/default_true.rb +41 -0
  51. data/lib/stockboy/translations/default_zero.rb +41 -0
  52. data/lib/stockboy/translations/integer.rb +33 -0
  53. data/lib/stockboy/translations/string.rb +33 -0
  54. data/lib/stockboy/translations/time.rb +41 -0
  55. data/lib/stockboy/translations/uk_date.rb +51 -0
  56. data/lib/stockboy/translations/us_date.rb +51 -0
  57. data/lib/stockboy/translator.rb +66 -0
  58. data/lib/stockboy/version.rb +3 -0
  59. data/spec/fixtures/.gitkeep +0 -0
  60. data/spec/fixtures/files/a_garbage.csv +1 -0
  61. data/spec/fixtures/files/test_data-20120101.csv +1 -0
  62. data/spec/fixtures/files/test_data-20120202.csv +1 -0
  63. data/spec/fixtures/files/z_garbage.csv +1 -0
  64. data/spec/fixtures/jobs/test_job.rb +1 -0
  65. data/spec/fixtures/soap/get_list/fault.xml +8 -0
  66. data/spec/fixtures/soap/get_list/success.xml +18 -0
  67. data/spec/fixtures/spreadsheets/test_data.xls +0 -0
  68. data/spec/fixtures/spreadsheets/test_row_options.xls +0 -0
  69. data/spec/fixtures/xml/body.xml +14 -0
  70. data/spec/spec_helper.rb +28 -0
  71. data/spec/stockboy/attribute_map_spec.rb +59 -0
  72. data/spec/stockboy/attribute_spec.rb +11 -0
  73. data/spec/stockboy/candidate_record_spec.rb +150 -0
  74. data/spec/stockboy/configuration_spec.rb +28 -0
  75. data/spec/stockboy/configurator_spec.rb +127 -0
  76. data/spec/stockboy/filter_chain_spec.rb +40 -0
  77. data/spec/stockboy/filter_spec.rb +41 -0
  78. data/spec/stockboy/filters/missing_email_spec.rb +26 -0
  79. data/spec/stockboy/filters_spec.rb +38 -0
  80. data/spec/stockboy/job_spec.rb +238 -0
  81. data/spec/stockboy/mapped_record_spec.rb +30 -0
  82. data/spec/stockboy/provider_spec.rb +34 -0
  83. data/spec/stockboy/providers/file_spec.rb +116 -0
  84. data/spec/stockboy/providers/ftp_spec.rb +143 -0
  85. data/spec/stockboy/providers/http_spec.rb +94 -0
  86. data/spec/stockboy/providers/imap_spec.rb +76 -0
  87. data/spec/stockboy/providers/soap_spec.rb +107 -0
  88. data/spec/stockboy/providers_spec.rb +38 -0
  89. data/spec/stockboy/readers/csv_spec.rb +68 -0
  90. data/spec/stockboy/readers/fixed_width_spec.rb +52 -0
  91. data/spec/stockboy/readers/spreadsheet_spec.rb +121 -0
  92. data/spec/stockboy/readers/xml_spec.rb +94 -0
  93. data/spec/stockboy/readers_spec.rb +30 -0
  94. data/spec/stockboy/source_record_spec.rb +19 -0
  95. data/spec/stockboy/template_file_spec.rb +30 -0
  96. data/spec/stockboy/translations/boolean_spec.rb +48 -0
  97. data/spec/stockboy/translations/date_spec.rb +38 -0
  98. data/spec/stockboy/translations/decimal_spec.rb +23 -0
  99. data/spec/stockboy/translations/default_empty_string_spec.rb +32 -0
  100. data/spec/stockboy/translations/default_false_spec.rb +25 -0
  101. data/spec/stockboy/translations/default_nil_spec.rb +32 -0
  102. data/spec/stockboy/translations/default_true_spec.rb +25 -0
  103. data/spec/stockboy/translations/default_zero_spec.rb +32 -0
  104. data/spec/stockboy/translations/integer_spec.rb +22 -0
  105. data/spec/stockboy/translations/string_spec.rb +22 -0
  106. data/spec/stockboy/translations/time_spec.rb +27 -0
  107. data/spec/stockboy/translations/uk_date_spec.rb +37 -0
  108. data/spec/stockboy/translations/us_date_spec.rb +37 -0
  109. data/spec/stockboy/translations_spec.rb +55 -0
  110. data/spec/stockboy/translator_spec.rb +27 -0
  111. data/stockboy.gemspec +32 -0
  112. metadata +305 -0
@@ -0,0 +1,116 @@
1
+ require 'spec_helper'
2
+ require 'stockboy/providers/file'
3
+
4
+ module Stockboy
5
+ describe Providers::File do
6
+ subject(:provider) { Stockboy::Providers::File.new }
7
+
8
+ it "should assign parameters" do
9
+ provider.file_dir = "fixtures/files"
10
+ provider.file_name = %r{import_20[1-9][0-9]-(0[1-9]|1[0-2])-([0-2][1-9]|3[0-1]).csv}
11
+ provider.file_newer = Date.today
12
+ provider.file_smaller = 1024**2
13
+ provider.file_larger = 1024
14
+ provider.pick = :first
15
+
16
+ provider.file_dir.should == "fixtures/files"
17
+ provider.file_name.should == %r{import_20[1-9][0-9]-(0[1-9]|1[0-2])-([0-2][1-9]|3[0-1]).csv}
18
+ provider.file_newer.should == Date.today
19
+ provider.file_smaller.should == 1024**2
20
+ provider.file_larger.should == 1024
21
+ provider.pick.should == :first
22
+ end
23
+
24
+ describe ".new" do
25
+ it "has no errors" do
26
+ provider.errors.messages.should be_empty
27
+ end
28
+
29
+ it "accepts block initialization" do
30
+ provider = Providers::File.new{ |f| f.file_dir 'fixtures/files' }
31
+ provider.file_dir.should == 'fixtures/files'
32
+ end
33
+ end
34
+
35
+ describe "#matching_file" do
36
+ subject(:provider) do
37
+ Providers::File.new do |f|
38
+ f.file_dir = RSpec.configuration.fixture_path.join("files")
39
+ end
40
+ end
41
+
42
+ it "returns the full path to the matching file name" do
43
+ provider.file_name = "test_data-*"
44
+ provider.matching_file.should end_with "fixtures/files/test_data-20120202.csv"
45
+ end
46
+ end
47
+
48
+ describe "#data" do
49
+ subject(:provider) do
50
+ Providers::File.new do |f|
51
+ f.file_dir = RSpec.configuration.fixture_path.join("files")
52
+ end
53
+ end
54
+
55
+ it "fails with an error if the file doesn't exist" do
56
+ provider.file_name = "missing-file.csv"
57
+ provider.data.should be_nil
58
+ provider.valid?.should == false
59
+ provider.errors[:base].should_not be_empty
60
+ end
61
+
62
+ it "finds last matching file from string glob" do
63
+ provider.file_name = "test_data-*.csv"
64
+ provider.data.should == "2012-02-02\n"
65
+ end
66
+
67
+ it "finds first matching file from string glob" do
68
+ provider.file_name = "test_data-*.csv"
69
+ provider.pick = :first
70
+ provider.data.should == "2012-01-01\n"
71
+ end
72
+
73
+ it "finds last matching file from regex" do
74
+ provider.file_name = /test_data/
75
+ provider.data.should == "2012-02-02\n"
76
+ end
77
+
78
+ context "with :since validation" do
79
+ let(:recently) { Time.now - 60 }
80
+
81
+ 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")
84
+ provider.file_name = '*.csv'
85
+ provider.since = recently
86
+
87
+ provider.data.should be_nil
88
+ provider.errors[:response].should include "No new files since #{recently}"
89
+ end
90
+ end
91
+ end
92
+
93
+ describe ".delete_data" do
94
+ let(:target) { ::Tempfile.new(['delete', '.csv']) }
95
+ let(:target_dir) { File.dirname(target) }
96
+ subject(:provider) { Providers::File.new(file_name: 'delete*.csv', file_dir: target_dir) }
97
+
98
+ after do
99
+ target.unlink
100
+ end
101
+
102
+ it "should raise an error when called blindly" do
103
+ expect_any_instance_of(::File).to_not receive(:delete)
104
+ expect { provider.delete_data }.to raise_error Stockboy::OutOfSequence
105
+ end
106
+
107
+ it "should call delete on the matched file" do
108
+ provider.matching_file
109
+
110
+ expect(::File).to receive(:delete).with(target.path)
111
+ provider.delete_data
112
+ end
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+ require 'stockboy/providers/ftp'
3
+
4
+ module Stockboy
5
+ describe Providers::FTP do
6
+
7
+ subject(:provider) do
8
+ Stockboy::Providers::FTP.new do |ftp|
9
+ ftp.host = "localhost.test"
10
+ ftp.username = "a"
11
+ ftp.password = "b"
12
+ ftp.binary = true
13
+ ftp.passive = true
14
+ ftp.file_name = '*.csv'
15
+ end
16
+ end
17
+
18
+ it "should assign parameters" do
19
+ ftp = Stockboy::Providers::FTP.new
20
+ ftp.host = "localhost.test"
21
+ ftp.username = "uuu"
22
+ ftp.password = "ppp"
23
+ ftp.file_dir = "files/here"
24
+ ftp.file_name = %r{import_20[1-9][0-9]-(0[1-9]|1[0-2])-([0-2][1-9]|3[0-1]).csv}
25
+
26
+ ftp.host.should == "localhost.test"
27
+ ftp.username.should == "uuu"
28
+ ftp.password.should == "ppp"
29
+ ftp.file_dir.should == "files/here"
30
+ ftp.file_name.should == %r{import_20[1-9][0-9]-(0[1-9]|1[0-2])-([0-2][1-9]|3[0-1]).csv}
31
+ end
32
+
33
+ describe ".new" do
34
+ it "has no errors" do
35
+ subject.errors.messages.should be_empty
36
+ end
37
+
38
+ it "accepts block initialization" do
39
+ ftp = Providers::FTP.new{ |f| f.host 'test2.local' }
40
+ ftp.host.should == 'test2.local'
41
+ end
42
+ end
43
+
44
+ describe "#client" do
45
+ it "should open connection to host with username and password" do
46
+ expect_connection
47
+
48
+ connection = false
49
+ provider.client { |f| connection = f }
50
+
51
+ connection.should be_a Net::FTP
52
+ connection.binary.should be_true
53
+ connection.passive.should be_true
54
+ end
55
+
56
+ it "should return yielded result" do
57
+ expect_connection
58
+
59
+ result = provider.client { |_| "a_file_name.csv" }
60
+
61
+ result.should == "a_file_name.csv"
62
+ end
63
+ end
64
+
65
+ describe "#data" do
66
+ it "adds an error on missing host" do
67
+ provider.host = nil
68
+ provider.data
69
+
70
+ provider.errors.include?(:host).should be_true
71
+ end
72
+
73
+ it "adds an error on missing file_name" do
74
+ provider.file_name = nil
75
+ provider.data
76
+
77
+ provider.errors.include?(:file_name).should be_true
78
+ end
79
+
80
+ it "downloads the last matching file" do
81
+ net_ftp = expect_connection
82
+ expect(net_ftp).to receive(:nlst).and_return ['20120101.csv', '20120102.csv']
83
+ expect(net_ftp).to receive(:get).with('20120102.csv', nil).and_return "DATA"
84
+ expect(provider).to receive(:validate_file).and_return true
85
+
86
+ provider.data.should == "DATA"
87
+ end
88
+
89
+ it "skips old files" do
90
+ net_ftp = expect_connection
91
+ expect(net_ftp).to receive(:nlst).and_return ['20120101.csv', '20120102.csv']
92
+ expect(net_ftp).to receive(:mtime).with('20120102.csv').and_return(Time.new(2009,01,01))
93
+ expect(net_ftp).to_not receive(:get)
94
+
95
+ provider.file_newer = Time.new(2010,1,1)
96
+
97
+ provider.data.should be_nil
98
+ end
99
+ end
100
+
101
+ describe "#matching_file" do
102
+ it "does not change until cleared" do
103
+ net_ftp = expect_connection
104
+ expect(net_ftp).to receive(:nlst).and_return ["1.csv", "2.csv"]
105
+
106
+ provider.matching_file.should == "2.csv"
107
+
108
+ net_ftp = expect_connection
109
+ expect(net_ftp).to receive(:nlst).and_return ["1.csv", "2.csv", "3.csv"]
110
+
111
+ provider.matching_file.should == "2.csv"
112
+ provider.clear
113
+ provider.matching_file.should == "3.csv"
114
+ end
115
+ end
116
+
117
+ describe "#delete_data" do
118
+ it "should raise an error when called blindly" do
119
+ expect_any_instance_of(Net::FTP).to_not receive(:delete)
120
+ expect { provider.delete_data }.to raise_error Stockboy::OutOfSequence
121
+ end
122
+
123
+ it "should delete the matching file" do
124
+ net_ftp = expect_connection
125
+ expect(net_ftp).to receive(:nlst).and_return ["1.csv", "2.csv"]
126
+
127
+ provider.matching_file.should == "2.csv"
128
+
129
+ net_ftp = expect_connection
130
+ expect(net_ftp).to receive(:delete).with("2.csv")
131
+
132
+ provider.delete_data.should == "2.csv"
133
+ end
134
+ end
135
+
136
+ def expect_connection(host="localhost.test", user="a", pass="b")
137
+ net_ftp = Net::FTP.new
138
+ expect(Net::FTP).to receive(:open).with(host, user, pass).and_yield(net_ftp)
139
+ net_ftp
140
+ end
141
+
142
+ end
143
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+ require 'stockboy/providers/http'
3
+
4
+ module Stockboy
5
+ describe Providers::HTTP do
6
+ subject(:provider) { Stockboy::Providers::HTTP.new }
7
+
8
+ it "should assign parameters from :uri option" do
9
+ provider.uri = "http://www.example.com/"
10
+ provider.query = {user: 'u'}
11
+ provider.method = :get
12
+
13
+ provider.uri.should == URI("http://www.example.com/?user=u")
14
+ provider.query.should == {user: 'u'}
15
+ provider.method.should == :get
16
+ end
17
+
18
+ it "should assign parameters from :get" do
19
+ provider.get = "http://www.example.com/"
20
+ provider.query = {user: 'u'}
21
+
22
+ provider.uri.should == URI("http://www.example.com/?user=u")
23
+ provider.query.should == {user: 'u'}
24
+ provider.method.should == :get
25
+ end
26
+
27
+ it "should assign parameters from :post" do
28
+ provider.post = "http://www.example.com/"
29
+ provider.query = {user: 'u'}
30
+
31
+ provider.uri.should == URI("http://www.example.com/?user=u")
32
+ provider.query.should == {user: 'u'}
33
+ provider.method.should == :post
34
+ end
35
+
36
+ describe ".new" do
37
+ its(:errors) { should be_empty }
38
+
39
+ it "accepts block DSL initialization" do
40
+ provider = Providers::HTTP.new do
41
+ get "http://www.example.com/"
42
+ query user: 'u'
43
+ end
44
+
45
+ provider.uri.should == URI("http://www.example.com/?user=u")
46
+ provider.query.should == { user: 'u' }
47
+ provider.method.should == :get
48
+ end
49
+ end
50
+
51
+ describe "validation" do
52
+ it "should not be valid without a method" do
53
+ provider.method = nil
54
+ provider.should_not be_valid
55
+ provider.errors.keys.should include(:method)
56
+ end
57
+
58
+ it "should not be valid without a uri" do
59
+ provider.uri = ""
60
+ provider.should_not be_valid
61
+ provider.errors.keys.should include(:uri)
62
+ end
63
+ end
64
+
65
+ describe "#data" do
66
+ let(:response) { HTTPI::Response.new(200, {}, '{"success":true}') }
67
+
68
+ subject(:provider) do
69
+ Providers::HTTP.new do |s|
70
+ s.uri = "http://www.example.com/"
71
+ s.query = {username: "user"}
72
+ s.method = :get
73
+ end
74
+ end
75
+
76
+ it "returns string body on success" do
77
+ expect(HTTPI).to receive(:request) { response }
78
+
79
+ provider.data.should == '{"success":true}'
80
+ end
81
+ end
82
+
83
+ describe "#client" do
84
+ it "yields a generic HTTP interface" do
85
+ provider.client do |http|
86
+ http.should respond_to :get
87
+ http.should respond_to :post
88
+ end
89
+ end
90
+ end
91
+
92
+ end
93
+ end
94
+
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require 'stockboy/providers/imap'
3
+
4
+ module Stockboy
5
+ describe Providers::IMAP do
6
+ subject(:provider) { Stockboy::Providers::IMAP.new }
7
+
8
+ it "should assign parameters" do
9
+ provider.host = "mail.localhost.test"
10
+ provider.username = "uuu"
11
+ provider.password = "ppp"
12
+ provider.mailbox = "INBOX/Data"
13
+ provider.subject = %r{New Records 20[1-9][0-9]-(0[1-9]|1[0-2])-([0-2][1-9]|3[0-1])}
14
+ provider.since = Date.new(2012,12,1)
15
+ provider.attachment = %r{data-[0-9]+\.csv}
16
+
17
+ provider.host.should == "mail.localhost.test"
18
+ provider.username.should == "uuu"
19
+ provider.password.should == "ppp"
20
+ provider.mailbox.should == "INBOX/Data"
21
+ provider.subject.should == %r{New Records 20[1-9][0-9]-(0[1-9]|1[0-2])-([0-2][1-9]|3[0-1])}
22
+ provider.attachment.should == %r{data-[0-9]+\.csv}
23
+ provider.since.should == Date.new(2012,12,1)
24
+ end
25
+
26
+ describe "deprecated options", pending: "implement deprecated_alias" do
27
+ it "promotes since instead of newer_than" do
28
+ provider = Providers::IMAP.new{ |f| f.newer_than Date.new(2012,12,1) }
29
+ provider.since.should == Date.new(2012,12,1)
30
+ end
31
+ end
32
+
33
+ describe ".new" do
34
+ it "has no errors" do
35
+ provider.errors.messages.should be_empty
36
+ end
37
+
38
+ it "accepts block initialization" do
39
+ provider = Providers::IMAP.new{ |f| f.host 'mail.test2.local' }
40
+ provider.host.should == 'mail.test2.local'
41
+ end
42
+ end
43
+
44
+ describe "#data" do
45
+
46
+ context "with no messages found" do
47
+ it "should be nil" do
48
+ allow(provider).to receive(:fetch_imap_message_keys).and_return []
49
+ provider.data.should be_nil
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ describe "#delete_data" do
56
+ let(:imap) { double(:imap) }
57
+
58
+ it "should raise an error when called blindly" do
59
+ expect { provider.delete_data }.to raise_error Stockboy::OutOfSequence
60
+ end
61
+
62
+ it "should call delete on the matching message" do
63
+ allow(provider).to receive(:client).and_yield(imap)
64
+ allow(provider).to receive(:fetch_imap_message_keys) { [5] }
65
+
66
+ provider.matching_message
67
+
68
+ expect(imap).to receive(:uid_store).with(5, "+FLAGS", [:Deleted])
69
+ expect(imap).to receive(:expunge)
70
+
71
+ provider.delete_data
72
+ end
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+ require 'stockboy/providers/soap'
3
+
4
+ module Stockboy
5
+ describe Providers::SOAP do
6
+ before(:all) { savon.mock! }
7
+ after(:all) { savon.unmock! }
8
+ subject(:provider) { Stockboy::Providers::SOAP.new }
9
+
10
+ it "should assign parameters" do
11
+ provider.wsdl = "http://api.example.com/?wsdl"
12
+ provider.request = :get_user
13
+ provider.namespace = "http://api.example.com/"
14
+ provider.message = {user: 'u', pass: 'p'}
15
+ provider.headers = {key: 'k'}
16
+
17
+ provider.wsdl.should == "http://api.example.com/?wsdl"
18
+ provider.request.should == :get_user
19
+ provider.namespace.should == "http://api.example.com/"
20
+ provider.message.should == {user: 'u', pass: 'p'}
21
+ provider.headers.should == {key: 'k'}
22
+ end
23
+
24
+ describe ".new" do
25
+ its(:errors) { should be_empty }
26
+
27
+ it "accepts block initialization" do
28
+ provider = Providers::SOAP.new do |p|
29
+ p.request = :get_user
30
+ p.endpoint = "http://api.example.com/v1"
31
+ p.namespace = "http://api.example.com/namespace"
32
+ p.wsdl = "http://api.example.com/?wsdl"
33
+ p.message = {user: 'u', pass: 'p'}
34
+ p.headers = {key: 'k'}
35
+ end
36
+
37
+ provider.request.should == :get_user
38
+ provider.endpoint.should == "http://api.example.com/v1"
39
+ provider.wsdl.should == "http://api.example.com/?wsdl"
40
+ provider.namespace.should == "http://api.example.com/namespace"
41
+ provider.message.should == {user: 'u', pass: 'p'}
42
+ provider.headers.should == {key: 'k'}
43
+ end
44
+ end
45
+
46
+ describe "validation" do
47
+ context "with a WSDL document" do
48
+ before { provider.wsdl = "http://api.example.com/?wsdl" }
49
+ it { should be_valid }
50
+ end
51
+
52
+ context "without a WSDL document" do
53
+ it "has error for blank endpoint & WSDL namespace" do
54
+ provider.valid?
55
+ provider.errors.keys.should include(:endpoint)
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "#client" do
61
+ it "yields a Savon client" do
62
+ provider.endpoint = "http://api.example.com/v1"
63
+ provider.namespace = ''
64
+ provider.client do |soap|
65
+ soap.should be_a Savon::Client
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "#data" do
71
+ let(:xml_success_fixture) do
72
+ File.read(RSpec.configuration.fixture_path.join "soap/get_list/success.xml")
73
+ end
74
+
75
+ let(:provider) do
76
+ Providers::SOAP.new do |s|
77
+ s.endpoint = "http://api.example.com/v1"
78
+ s.namespace = ''
79
+ s.request = :get_list
80
+ s.message = {username: "user", password: "pass"}
81
+ end
82
+ end
83
+
84
+ subject(:response) do
85
+ savon.expects(:get_list)
86
+ .with(message: {username: 'user', password: 'pass'})
87
+ .returns(xml_success_fixture)
88
+ provider.data
89
+ end
90
+
91
+ it "returns hash data on success" do
92
+ should be_a Hash
93
+ end
94
+
95
+ it "uses string keys" do
96
+ response.keys.each { |k| k.should be_a String }
97
+ end
98
+
99
+ it "shares key string objects from a common pool" do
100
+ cases = response["MultiNamespacedEntryResponse"]["history"]["case"]
101
+ text_keys = cases.map { |c| c.keys[c.keys.index("logText")] }
102
+ text_keys[0].should be text_keys[1]
103
+ end
104
+
105
+ end
106
+ end
107
+ end