allscripts_unity_client 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.gitignore +20 -0
  2. data/.travis.yml +3 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE +22 -0
  5. data/README.md +180 -0
  6. data/Rakefile +7 -0
  7. data/allscripts_unity_client.gemspec +39 -0
  8. data/lib/allscripts_unity_client.rb +43 -0
  9. data/lib/allscripts_unity_client/client.rb +594 -0
  10. data/lib/allscripts_unity_client/client_driver.rb +95 -0
  11. data/lib/allscripts_unity_client/json_client_driver.rb +110 -0
  12. data/lib/allscripts_unity_client/json_unity_request.rb +33 -0
  13. data/lib/allscripts_unity_client/json_unity_response.rb +27 -0
  14. data/lib/allscripts_unity_client/soap_client_driver.rb +128 -0
  15. data/lib/allscripts_unity_client/timezone.rb +99 -0
  16. data/lib/allscripts_unity_client/unity_request.rb +63 -0
  17. data/lib/allscripts_unity_client/unity_response.rb +110 -0
  18. data/lib/allscripts_unity_client/utilities.rb +66 -0
  19. data/lib/allscripts_unity_client/version.rb +3 -0
  20. data/spec/allscripts_unity_client_spec.rb +57 -0
  21. data/spec/client_driver_spec.rb +71 -0
  22. data/spec/client_spec.rb +406 -0
  23. data/spec/factories/allscripts_unity_client_parameters_factory.rb +13 -0
  24. data/spec/factories/client_driver_factory.rb +14 -0
  25. data/spec/factories/client_factory.rb +7 -0
  26. data/spec/factories/json_client_driver_factory.rb +3 -0
  27. data/spec/factories/json_unity_request_factory.rb +3 -0
  28. data/spec/factories/json_unity_response_factory.rb +3 -0
  29. data/spec/factories/magic_request_factory.rb +33 -0
  30. data/spec/factories/soap_client_driver_factory.rb +3 -0
  31. data/spec/factories/timezone_factory.rb +7 -0
  32. data/spec/factories/unity_request_factory.rb +10 -0
  33. data/spec/factories/unity_response_factory.rb +8 -0
  34. data/spec/fixtures/attributes_hash.yml +15 -0
  35. data/spec/fixtures/date_hash.yml +8 -0
  36. data/spec/fixtures/date_string_hash.yml +8 -0
  37. data/spec/fixtures/error.json +3 -0
  38. data/spec/fixtures/get_providers.json +69 -0
  39. data/spec/fixtures/get_providers.xml +119 -0
  40. data/spec/fixtures/get_providers_json.yml +65 -0
  41. data/spec/fixtures/get_providers_xml.yml +270 -0
  42. data/spec/fixtures/get_security_token.json +1 -0
  43. data/spec/fixtures/get_security_token.xml +7 -0
  44. data/spec/fixtures/get_server_info.json +10 -0
  45. data/spec/fixtures/get_server_info.xml +40 -0
  46. data/spec/fixtures/get_server_info_json.yml +8 -0
  47. data/spec/fixtures/get_server_info_xml.yml +55 -0
  48. data/spec/fixtures/no_attributes_hash.yml +7 -0
  49. data/spec/fixtures/retire_security_token.json +1 -0
  50. data/spec/fixtures/retire_security_token.xml +5 -0
  51. data/spec/fixtures/soap_fault.xml +13 -0
  52. data/spec/fixtures/string_keyed_hash.yml +8 -0
  53. data/spec/fixtures/symbol_keyed_hash.yml +8 -0
  54. data/spec/json_client_driver_spec.rb +209 -0
  55. data/spec/json_unity_request_spec.rb +37 -0
  56. data/spec/json_unity_response_spec.rb +44 -0
  57. data/spec/soap_client_driver_spec.rb +201 -0
  58. data/spec/spec_helper.rb +44 -0
  59. data/spec/support/fixture_loader.rb +22 -0
  60. data/spec/support/shared_examples_for_client_driver.rb +139 -0
  61. data/spec/support/shared_examples_for_unity_request.rb +94 -0
  62. data/spec/support/shared_examples_for_unity_response.rb +26 -0
  63. data/spec/timezone_spec.rb +161 -0
  64. data/spec/unity_request_spec.rb +37 -0
  65. data/spec/unity_response_spec.rb +36 -0
  66. data/spec/utilities_spec.rb +69 -0
  67. metadata +323 -0
@@ -0,0 +1,201 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'SOAPClientDriver' do
4
+ include Savon::SpecHelper
5
+ it_behaves_like 'a client driver'
6
+
7
+ subject do
8
+ client_driver = FactoryGirl.build(:soap_client_driver)
9
+ client_driver.security_token = SecureRandom.uuid
10
+ client_driver
11
+ end
12
+
13
+ let(:get_server_info) { FixtureLoader.load_file("get_server_info.xml") }
14
+ let(:get_security_token) { FixtureLoader.load_file("get_security_token.xml") }
15
+ let(:retire_security_token) { FixtureLoader.load_file("retire_security_token.xml") }
16
+ let(:soap_fault) { FixtureLoader.load_file("soap_fault.xml") }
17
+ let(:url) { Faker::Internet.url }
18
+
19
+ before(:all) { savon.mock! }
20
+ after(:all) { savon.unmock! }
21
+
22
+ describe '#initialize' do
23
+ context 'when nil is given for base_unity_url' do
24
+ it { expect { FactoryGirl.build(:soap_client_driver, :base_unity_url => nil) }.to raise_error(ArgumentError) }
25
+ end
26
+
27
+ context 'when nil is given for username' do
28
+ it { expect { FactoryGirl.build(:soap_client_driver, :username => nil) }.to raise_error(ArgumentError) }
29
+ end
30
+
31
+ context 'when nil is given for password' do
32
+ it { expect { FactoryGirl.build(:soap_client_driver, :password => nil) }.to raise_error(ArgumentError) }
33
+ end
34
+
35
+ context 'when nil is given for appname' do
36
+ it { expect { FactoryGirl.build(:soap_client_driver, :appname => nil) }.to raise_error(ArgumentError) }
37
+ end
38
+
39
+ context 'when given a base_unity_url with a trailing /' do
40
+ it 'sets @base_unity_url without the trailing /' do
41
+ client_driver = FactoryGirl.build(:soap_client_driver, :base_unity_url => "http://www.example.com/")
42
+ expect(client_driver.base_unity_url).to eq("http://www.example.com")
43
+ end
44
+ end
45
+
46
+ context 'when nil is given for timezone' do
47
+ it 'sets @timezone to UTC' do
48
+ client_driver = FactoryGirl.build(:soap_client_driver, :timezone => nil)
49
+ utc_timezone = FactoryGirl.build(:timezone, :zone_identifier => "UTC")
50
+ expect(client_driver.timezone.tzinfo).to eq(utc_timezone.tzinfo)
51
+ end
52
+ end
53
+
54
+ context 'when nil is given for proxy' do
55
+ it 'sets Savon proxy option to nil' do
56
+ client_driver = FactoryGirl.build(:soap_client_driver, :proxy => nil)
57
+ expect(client_driver.savon_client.globals.instance_variable_get("@options")[:proxy]).to be_nil
58
+ end
59
+ end
60
+
61
+ context 'when proxy is given' do
62
+ it 'sets Savon proxy option to the given url' do
63
+ client_driver = FactoryGirl.build(:soap_client_driver, :proxy => url)
64
+ expect(client_driver.savon_client.globals.instance_variable_get("@options")[:proxy]).to eq(url)
65
+ end
66
+ end
67
+
68
+ context 'when nil is given for logger' do
69
+ it 'sets @logger to Logger' do
70
+ client_driver = FactoryGirl.build(:soap_client_driver, :logger => nil)
71
+ expect(client_driver.logger).to be_instance_of(Logger)
72
+ end
73
+ end
74
+
75
+ context 'when logger is set' do
76
+ it 'sets @logger to logger' do
77
+ logger = double("logger")
78
+ client_driver = FactoryGirl.build(:soap_client_driver, :logger => logger)
79
+ expect(client_driver.logger).to be(logger)
80
+ end
81
+ end
82
+ end
83
+
84
+ describe '#client_type' do
85
+ it { expect(subject.client_type).to be(:soap) }
86
+ end
87
+
88
+ describe '#magic' do
89
+ before(:each) {
90
+ allow(subject).to receive(:start_timer)
91
+ allow(subject).to receive(:end_timer)
92
+ allow(subject).to receive(:log_magic)
93
+ }
94
+
95
+ it 'should send a SOAP request to Magic endpoint' do
96
+ savon.expects("Magic").with(:message => :any).returns(get_server_info)
97
+ subject.magic
98
+ end
99
+
100
+ context 'when a Savon::SOAPFault is raised' do
101
+ it 'should raise an APIError' do
102
+ savon.expects("Magic").with(:message => :any).returns({ code: 500, headers: {}, body: soap_fault })
103
+ expect { subject.magic }.to raise_error(AllscriptsUnityClient::APIError)
104
+ end
105
+ end
106
+
107
+ it 'should call start_timer' do
108
+ savon.expects("Magic").with(:message => :any).returns(get_server_info)
109
+ subject.magic
110
+ expect(subject).to have_received(:start_timer)
111
+ end
112
+
113
+ it 'should call end_timer' do
114
+ savon.expects("Magic").with(:message => :any).returns(get_server_info)
115
+ subject.magic
116
+ expect(subject).to have_received(:start_timer)
117
+ end
118
+
119
+ it 'should call log_magic' do
120
+ savon.expects("Magic").with(:message => :any).returns(get_server_info)
121
+ subject.magic
122
+ expect(subject).to have_received(:log_magic)
123
+ end
124
+ end
125
+
126
+ describe '#get_security_token!' do
127
+ before(:each) {
128
+ allow(subject).to receive(:start_timer)
129
+ allow(subject).to receive(:end_timer)
130
+ allow(subject).to receive(:log_get_security_token)
131
+ }
132
+
133
+ it 'should send a SOAP request to GetSecurityToken endpoint' do
134
+ savon.expects("GetSecurityToken").with(:message => :any).returns(get_security_token)
135
+ subject.get_security_token!
136
+ end
137
+
138
+ context 'when a Savon::SOAPFault is raised' do
139
+ it 'should raise an APIError' do
140
+ savon.expects("GetSecurityToken").with(:message => :any).returns({ code: 500, headers: {}, body: soap_fault })
141
+ expect { subject.get_security_token! }.to raise_error(AllscriptsUnityClient::APIError)
142
+ end
143
+ end
144
+
145
+ it 'should call start_timer' do
146
+ savon.expects("GetSecurityToken").with(:message => :any).returns(get_security_token)
147
+ subject.get_security_token!
148
+ expect(subject).to have_received(:start_timer)
149
+ end
150
+
151
+ it 'should call end_timer' do
152
+ savon.expects("GetSecurityToken").with(:message => :any).returns(get_security_token)
153
+ subject.get_security_token!
154
+ expect(subject).to have_received(:start_timer)
155
+ end
156
+
157
+ it 'should call log_get_security_token' do
158
+ savon.expects("GetSecurityToken").with(:message => :any).returns(get_security_token)
159
+ subject.get_security_token!
160
+ expect(subject).to have_received(:log_get_security_token)
161
+ end
162
+ end
163
+
164
+ describe '#retire_security_token!' do
165
+ before(:each) {
166
+ allow(subject).to receive(:start_timer)
167
+ allow(subject).to receive(:end_timer)
168
+ allow(subject).to receive(:log_retire_security_token)
169
+ }
170
+
171
+ it 'should send a SOAP request to RetireSecurityToken endpoint' do
172
+ savon.expects("RetireSecurityToken").with(:message => :any).returns(retire_security_token)
173
+ subject.retire_security_token!
174
+ end
175
+
176
+ context 'when a Savon::SOAPFault is raised' do
177
+ it 'should raise an APIError' do
178
+ savon.expects("RetireSecurityToken").with(:message => :any).returns({ code: 500, headers: {}, body: soap_fault })
179
+ expect { subject.retire_security_token! }.to raise_error(AllscriptsUnityClient::APIError)
180
+ end
181
+ end
182
+
183
+ it 'should call start_timer' do
184
+ savon.expects("RetireSecurityToken").with(:message => :any).returns(retire_security_token)
185
+ subject.retire_security_token!
186
+ expect(subject).to have_received(:start_timer)
187
+ end
188
+
189
+ it 'should call end_timer' do
190
+ savon.expects("RetireSecurityToken").with(:message => :any).returns(retire_security_token)
191
+ subject.retire_security_token!
192
+ expect(subject).to have_received(:start_timer)
193
+ end
194
+
195
+ it 'should call log_retire_security_token' do
196
+ savon.expects("RetireSecurityToken").with(:message => :any).returns(retire_security_token)
197
+ subject.retire_security_token!
198
+ expect(subject).to have_received(:log_retire_security_token)
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,44 @@
1
+ require 'pathname'
2
+ require 'simplecov'
3
+ require 'coveralls'
4
+
5
+ # Configure coverage stats.
6
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
7
+ SimpleCov::Formatter::HTMLFormatter,
8
+ Coveralls::SimpleCov::Formatter
9
+ ]
10
+ SimpleCov.start do
11
+ add_filter do |source_file|
12
+ filename = Pathname.new(source_file.filename).basename
13
+ ignored_files = [
14
+ "version.rb",
15
+ "allscripts_unity_client.gemspec",
16
+ "Gemfile",
17
+ "Rakefile"
18
+ ]
19
+
20
+ ignored_files.include?(filename) || source_file.filename.include?("spec/")
21
+ end
22
+ end
23
+
24
+ lib = File.expand_path('../lib/', __FILE__)
25
+ $:.unshift lib unless $:.include?(lib)
26
+
27
+ require 'allscripts_unity_client'
28
+
29
+ require 'rspec'
30
+ require 'webmock/rspec'
31
+ require 'savon/mock/spec_helper'
32
+ require 'securerandom'
33
+ require 'faker'
34
+ require 'factory_girl'
35
+ require 'json'
36
+
37
+ # Include all support files
38
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
39
+
40
+ # Include all factories
41
+ FactoryGirl.find_definitions
42
+
43
+ RSpec.configure do |config|
44
+ end
@@ -0,0 +1,22 @@
1
+ require 'yaml'
2
+ require 'json'
3
+
4
+ class FixtureLoader
5
+ def self.load_yaml(filename)
6
+ YAML.load(read(filename))
7
+ end
8
+
9
+ def self.load_json(filename)
10
+ JSON.parse(read(filename))
11
+ end
12
+
13
+ def self.load_file(filename)
14
+ read(filename)
15
+ end
16
+
17
+ private
18
+
19
+ def self.read(filename)
20
+ File.read(File.expand_path("../../fixtures/#{filename}", __FILE__))
21
+ end
22
+ end
@@ -0,0 +1,139 @@
1
+ shared_examples 'a client driver' do
2
+ describe '#security_token?' do
3
+ context 'when @security_token is nil' do
4
+ it do
5
+ subject.security_token = nil
6
+ expect(subject.security_token?).to be_false
7
+ end
8
+ end
9
+
10
+ context 'when @security_token is not nil' do
11
+ it do
12
+ subject.security_token = "security token"
13
+ expect(subject.security_token?).to be_true
14
+ end
15
+ end
16
+ end
17
+
18
+ describe "#log?" do
19
+ context 'when log is false' do
20
+ it 'return false' do
21
+ subject.log = false
22
+ expect(subject.log).to be_false
23
+ end
24
+ end
25
+
26
+ context 'when log is true' do
27
+ it 'return false' do
28
+ subject.log = true
29
+ expect(subject.log).to be_true
30
+ end
31
+ end
32
+ end
33
+
34
+ describe "#log_get_security_token" do
35
+ it 'should call log_info' do
36
+ allow(subject).to receive(:log_info)
37
+ subject.send(:log_get_security_token)
38
+ expect(subject).to have_received(:log_info)
39
+ end
40
+ end
41
+
42
+ describe "#log_retire_security_token" do
43
+ it 'should call log_info' do
44
+ allow(subject).to receive(:log_info)
45
+ subject.send(:log_retire_security_token)
46
+ expect(subject).to have_received(:log_info)
47
+ end
48
+ end
49
+
50
+ describe "#log_magic" do
51
+ it 'should call log_info' do
52
+ allow(subject).to receive(:log_info)
53
+ subject.send(:log_magic, double(:parameters => { :action => "action" }))
54
+ expect(subject).to have_received(:log_info)
55
+ end
56
+
57
+ context 'when given nil for request' do
58
+ it { expect { subject.send(:log_magic, nil) }.to raise_error(ArgumentError) }
59
+ end
60
+ end
61
+
62
+ describe '#log_info' do
63
+ context 'when log? is true' do
64
+ it 'should call @logger.info' do
65
+ subject.log = true
66
+ allow(subject.logger).to receive(:info)
67
+ subject.send(:log_info, "test")
68
+ expect(subject.logger).to have_received(:info)
69
+ end
70
+ end
71
+
72
+ context 'when log? is false' do
73
+ it 'should not call @logger.info' do
74
+ subject.log = false
75
+ allow(subject.logger).to receive(:info)
76
+ subject.send(:log_info, "test")
77
+ expect(subject.logger).to_not have_received(:info)
78
+ end
79
+ end
80
+
81
+ context 'when given nil for message' do
82
+ it 'should not call @logger.info' do
83
+ subject.log = true
84
+ allow(subject.logger).to receive(:info)
85
+ subject.send(:log_info, nil)
86
+ expect(subject.logger).to_not have_received(:info)
87
+ end
88
+ end
89
+
90
+ context 'when @logger is nil and log is true' do
91
+ it 'should not call @logger.info' do
92
+ subject.log = true
93
+ subject.logger = nil
94
+ expect { subject.send(:log_info, "test") }.to_not raise_error
95
+ end
96
+ end
97
+
98
+ context 'when @timer is nil and log is true' do
99
+ it 'should not include seconds in the log' do
100
+ subject.log = true
101
+ subject.instance_variable_set("@timer", nil)
102
+ allow(subject.logger).to receive(:info)
103
+ subject.send(:log_info, "test")
104
+ expect(subject.logger).to_not have_received(:info).with(match(/seconds/))
105
+ end
106
+ end
107
+
108
+ context 'when @timer is not nil and log is true' do
109
+ it 'should include seconds in log' do
110
+ subject.log = true
111
+ subject.instance_variable_set("@timer", 1.2)
112
+ allow(subject.logger).to receive(:info)
113
+ subject.send(:log_info, "test")
114
+ expect(subject.logger).to have_received(:info).with(match(/seconds/))
115
+ end
116
+ end
117
+ end
118
+
119
+ describe '#start_timer' do
120
+ it 'sets @start_time' do
121
+ subject.send(:start_timer)
122
+ expect(subject.instance_variable_get("@start_time")).to_not be_nil
123
+ end
124
+ end
125
+
126
+ describe '#end_timer' do
127
+ it 'sets @end_time' do
128
+ subject.send(:start_timer)
129
+ subject.send(:end_timer)
130
+ expect(subject.instance_variable_get("@end_time")).to_not be_nil
131
+ end
132
+
133
+ it 'sets @timer to @end_time - @start_time' do
134
+ subject.send(:start_timer)
135
+ subject.send(:end_timer)
136
+ expect(subject.instance_variable_get("@timer")).to eq(subject.instance_variable_get("@end_time") - subject.instance_variable_get("@start_time"))
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,94 @@
1
+ shared_examples 'a unity request' do
2
+ let(:magic_request) { FactoryGirl.build(:magic_request) }
3
+
4
+ describe '#to_hash' do
5
+ it ':action maps to Action' do
6
+ subject.parameters = FactoryGirl.build(:magic_request, :action => 'Action')
7
+ expect(subject.to_hash['Action']).to eq('Action')
8
+ end
9
+
10
+ it ':appname maps to Appname' do
11
+ subject.parameters = FactoryGirl.build(:magic_request, :appname => 'Appname')
12
+ expect(subject.to_hash['Appname']).to eq('Appname')
13
+ end
14
+
15
+ it ':patientid maps to PatientID' do
16
+ subject.parameters = FactoryGirl.build(:magic_request, :patientid => 'PatientID')
17
+ expect(subject.to_hash['PatientID']).to eq('PatientID')
18
+ end
19
+
20
+ it ':token maps to Token' do
21
+ subject.parameters = FactoryGirl.build(:magic_request, :token => 'Token')
22
+ expect(subject.to_hash['Token']).to eq('Token')
23
+ end
24
+
25
+ it ':parameter1 maps to Parameter1' do
26
+ subject.parameters = FactoryGirl.build(:magic_request, :parameter1 => 'Parameter1')
27
+ expect(subject.to_hash['Parameter1']).to eq('Parameter1')
28
+ end
29
+
30
+ it ':parameter2 maps to Parameter2' do
31
+ subject.parameters = FactoryGirl.build(:magic_request, :parameter2 => 'Parameter2')
32
+ expect(subject.to_hash['Parameter2']).to eq('Parameter2')
33
+ end
34
+
35
+ it ':parameter3 maps to Parameter3' do
36
+ subject.parameters = FactoryGirl.build(:magic_request, :parameter3 => 'Parameter3')
37
+ expect(subject.to_hash['Parameter3']).to eq('Parameter3')
38
+ end
39
+
40
+ it ':parameter4 maps to Parameter4' do
41
+ subject.parameters = FactoryGirl.build(:magic_request, :parameter4 => 'Parameter4')
42
+ expect(subject.to_hash['Parameter4']).to eq('Parameter4')
43
+ end
44
+
45
+ it ':parameter5 maps to Parameter5' do
46
+ subject.parameters = FactoryGirl.build(:magic_request, :parameter5 => 'Parameter5')
47
+ expect(subject.to_hash['Parameter5']).to eq('Parameter5')
48
+ end
49
+
50
+ it ':parameter6 maps to Parameter6' do
51
+ subject.parameters = FactoryGirl.build(:magic_request, :parameter6 => 'Parameter6')
52
+ expect(subject.to_hash['Parameter6']).to eq('Parameter6')
53
+ end
54
+
55
+ it 'calls process_date on parameters' do
56
+ subject.parameters = FactoryGirl.build(:populated_magic_request)
57
+ allow(subject).to receive(:process_date)
58
+ subject.to_hash
59
+ expect(subject).to have_received(:process_date).exactly(6).times
60
+ end
61
+ end
62
+
63
+ describe '#process_date' do
64
+ context 'when given nil' do
65
+ it { expect(subject.send(:process_date, nil)).to be_nil }
66
+ end
67
+
68
+ context 'when given a non-date string' do
69
+ it do
70
+ not_a_date = Faker::Name.name
71
+ expect(subject.send(:process_date, not_a_date)).to eq(not_a_date)
72
+ end
73
+ end
74
+
75
+ context 'when given a date string' do
76
+ it do
77
+ date = "2013-10-24"
78
+ expect(subject.send(:process_date, date)).to be_instance_of(Date)
79
+ end
80
+ end
81
+
82
+ context 'when given a Date' do
83
+ it { expect(subject.send(:process_date, Date.today)).to be_instance_of(Date) }
84
+ end
85
+
86
+ context 'when given a Time' do
87
+ it { expect(subject.send(:process_date, Time.now)).to be_instance_of(Time) }
88
+ end
89
+
90
+ context 'when given a DateTime' do
91
+ it { expect(subject.send(:process_date, DateTime.now)).to be_instance_of(DateTime) }
92
+ end
93
+ end
94
+ end