allscripts_unity_client 1.0.3

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.
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