qbwc 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -1
  3. data/.travis.yml +6 -0
  4. data/README.md +152 -144
  5. data/Rakefile +7 -1
  6. data/lib/generators/qbwc/install/install_generator.rb +20 -4
  7. data/lib/generators/qbwc/install/templates/config/qbwc.rb +42 -26
  8. data/lib/generators/qbwc/install/templates/controllers/qbwc_controller.rb +2 -38
  9. data/lib/generators/qbwc/install/templates/db/migrate/create_qbwc_jobs.rb +15 -0
  10. data/lib/generators/qbwc/install/templates/db/migrate/create_qbwc_sessions.rb +16 -0
  11. data/lib/qbwc.rb +107 -71
  12. data/lib/qbwc/active_record.rb +6 -0
  13. data/lib/qbwc/active_record/job.rb +111 -0
  14. data/lib/qbwc/active_record/session.rb +52 -0
  15. data/lib/qbwc/controller.rb +176 -0
  16. data/lib/qbwc/job.rb +81 -18
  17. data/lib/qbwc/railtie.rb +8 -0
  18. data/lib/qbwc/request.rb +14 -23
  19. data/lib/qbwc/session.rb +100 -72
  20. data/lib/qbwc/version.rb +1 -1
  21. data/lib/qbwc/worker.rb +16 -0
  22. data/qbwc.gemspec +11 -5
  23. data/test/qbwc/controllers/controller_test.rb +157 -0
  24. data/test/qbwc/integration/job_management_test.rb +86 -0
  25. data/test/qbwc/integration/request_generation_test.rb +340 -0
  26. data/test/qbwc/integration/response_test.rb +303 -0
  27. data/test/qbwc/integration/routes_test.rb +38 -0
  28. data/test/qbwc/integration/session_test.rb +94 -0
  29. data/test/test_helper.rb +248 -0
  30. data/test/wash_out_helper.rb +76 -0
  31. metadata +133 -55
  32. data/Gemfile.lock +0 -72
  33. data/lib/qbwc/soap_wrapper.rb +0 -35
  34. data/lib/qbwc/soap_wrapper/QBWebConnectorSvc.rb +0 -69
  35. data/lib/qbwc/soap_wrapper/QBWebConnectorSvc.wsdl +0 -312
  36. data/lib/qbwc/soap_wrapper/default.rb +0 -198
  37. data/lib/qbwc/soap_wrapper/defaultMappingRegistry.rb +0 -163
  38. data/lib/qbwc/soap_wrapper/defaultServant.rb +0 -133
  39. data/spec/spec_helper.rb +0 -17
@@ -0,0 +1,303 @@
1
+ $:<< File.expand_path(File.dirname(__FILE__) + '/../..')
2
+ require 'test_helper.rb'
3
+
4
+ class ResponseTest < ActionDispatch::IntegrationTest
5
+
6
+ WARN_RESPONSE = {
7
+ :response => QBWC_CUSTOMER_QUERY_RESPONSE_WARN,
8
+ :code => '500',
9
+ :severity => 'Warn',
10
+ :message => QBWC_CUSTOMER_QUERY_STATUS_MESSAGE_WARN,
11
+ }
12
+ ERROR_RESPONSE = {
13
+ :response => QBWC_CUSTOMER_QUERY_RESPONSE_ERROR,
14
+ :code => '3120',
15
+ :severity => 'Error',
16
+ :message => QBWC_CUSTOMER_QUERY_STATUS_MESSAGE_ERROR,
17
+ }
18
+
19
+ def setup
20
+ ResponseTest.app = Rails.application
21
+ QBWC.on_error = :stop
22
+ QBWC.clear_jobs
23
+
24
+ $HANDLE_RESPONSE_EXECUTED = false
25
+ $HANDLE_RESPONSE_DATA = nil
26
+ $HANDLE_RESPONSE_IS_PASSED_DATA = false
27
+ end
28
+
29
+ def _receive_responses(*responses)
30
+
31
+ # Simulate controller authenticate
32
+ ticket_string = QBWC::ActiveRecord::Session.new(QBWC_USERNAME, COMPANY).ticket
33
+ session = QBWC::Session.new(nil, COMPANY)
34
+
35
+ responses.each do |resp|
36
+ expect_error = "QBWC #{resp[:severity].upcase}: #{resp[:code]} - #{resp[:message]}"
37
+
38
+ # Simulate controller receive_response
39
+ $HANDLE_RESPONSE_EXECUTED = false
40
+ session.response = resp[:response]
41
+ assert_equal resp[:progress], session.progress unless resp[:progress].nil?
42
+ assert_equal resp[:code], session.status_code
43
+ assert_equal resp[:severity], session.status_severity
44
+ assert_equal expect_error, session.error
45
+ assert $HANDLE_RESPONSE_EXECUTED
46
+
47
+ # Simulate controller send_request
48
+ if session.progress == 100
49
+ assert_nil(session.next_request)
50
+ return
51
+ end
52
+
53
+ assert_not_nil(session.next_request)
54
+ end
55
+
56
+ end
57
+
58
+ def _test_warning_then_error(expected_progress1 = 50)
59
+ warn = WARN_RESPONSE.merge(:progress => expected_progress1)
60
+ error = ERROR_RESPONSE.merge(:progress => 100)
61
+
62
+ _receive_responses(warn, error)
63
+ end
64
+
65
+ def _test_error_then_warning(expected_progress1 = 50)
66
+ error = ERROR_RESPONSE.merge(:progress => expected_progress1)
67
+ warn = WARN_RESPONSE.merge(:progress => 100)
68
+
69
+ _receive_responses(error, warn)
70
+ end
71
+
72
+ def _test_error_then_warning_that_stops
73
+ _test_error_then_warning(100)
74
+ end
75
+
76
+ class HandleResponseWithDataWorker < QBWC::Worker
77
+ def requests(job)
78
+ {:customer_query_rq => {:full_name => 'Quincy Bob William Carlos'}}
79
+ end
80
+ def handle_response(response, session, job, request, data)
81
+ $HANDLE_RESPONSE_EXECUTED = true
82
+ $HANDLE_RESPONSE_IS_PASSED_DATA = (data == $HANDLE_RESPONSE_DATA)
83
+ end
84
+ end
85
+
86
+ test "handle_response is passed data" do
87
+ $HANDLE_RESPONSE_DATA = {:first => {:second => 2, :third => '3'} }
88
+ $HANDLE_RESPONSE_IS_PASSED_DATA = false
89
+ QBWC.add_job(:integration_test, true, '', HandleResponseWithDataWorker, nil, $HANDLE_RESPONSE_DATA)
90
+ session = QBWC::Session.new('foo', '')
91
+ assert_not_nil session.next_request
92
+ simulate_response(session, QBWC_CUSTOMER_ADD_RESPONSE_LONG)
93
+ assert_nil session.next_request
94
+ assert $HANDLE_RESPONSE_IS_PASSED_DATA
95
+ end
96
+
97
+ class HandleResponseRaisesExceptionWorker < QBWC::Worker
98
+ def requests(job)
99
+ {:customer_query_rq => {:full_name => 'Quincy Bob William Carlos'}}
100
+ end
101
+ def handle_response(response, session, job, request, data)
102
+ raise "Exception in handle_response"
103
+ end
104
+ end
105
+
106
+ test "handle_response raises exception" do
107
+ QBWC.add_job(:integration_test, true, '', HandleResponseRaisesExceptionWorker)
108
+ session = QBWC::Session.new('foo', '')
109
+ assert_not_nil session.next_request
110
+ simulate_response(session)
111
+ assert_nil session.next_request
112
+ assert_equal "Exception in handle_response", session.error
113
+ end
114
+
115
+ class HandleResponseOmitsJobWorker < QBWC::Worker
116
+ def requests(job)
117
+ {:customer_query_rq => {:full_name => 'Quincy Bob William Carlos'}}
118
+ end
119
+ def handle_response(*response)
120
+ $HANDLE_RESPONSE_EXECUTED = true
121
+ end
122
+ end
123
+
124
+ test "handle_response must use splat operator when omitting remaining arguments" do
125
+ QBWC.add_job(:integration_test, true, '', HandleResponseOmitsJobWorker)
126
+ session = QBWC::Session.new('foo', '')
127
+ assert_not_nil session.next_request
128
+ simulate_response(session)
129
+ assert_nil session.next_request
130
+ assert $HANDLE_RESPONSE_EXECUTED
131
+ end
132
+
133
+ class QueryAndDeleteWorker < QBWC::Worker
134
+ def requests(job)
135
+ {:name => 'mrjoecustomer'}
136
+ end
137
+
138
+ def handle_response(resp, session, job, request, data)
139
+ QBWC.delete_job(job.name)
140
+ end
141
+ end
142
+
143
+ test "processes warning responses and deletes the job" do
144
+ QBWC.on_error = :stop
145
+
146
+ # Add a job
147
+ QBWC.add_job(:query_joe_customer, true, COMPANY, QueryAndDeleteWorker)
148
+
149
+ # Simulate controller authenticate
150
+ ticket_string = QBWC::ActiveRecord::Session.new(QBWC_USERNAME, COMPANY).ticket
151
+ session = QBWC::Session.new(nil, COMPANY)
152
+
153
+ # Simulate controller receive_response
154
+ session.response = QBWC_CUSTOMER_QUERY_RESPONSE_WARN
155
+ assert_equal 100, session.progress
156
+
157
+ # Simulate controller send_request
158
+ assert_nil session.next_request
159
+
160
+ # Simulate arbitrary controller action
161
+ session = QBWC::ActiveRecord::Session.get(ticket_string) # simulated get_session
162
+ session.save # simulated save_session
163
+
164
+ end
165
+
166
+ test "processes error responses and deletes the job" do
167
+ QBWC.on_error = :stop
168
+
169
+ # Add a job
170
+ QBWC.add_job(:query_joe_customer, true, COMPANY, QueryAndDeleteWorker)
171
+
172
+ # Simulate controller authenticate
173
+ ticket_string = QBWC::ActiveRecord::Session.new(QBWC_USERNAME, COMPANY).ticket
174
+ session = QBWC::Session.new(nil, COMPANY)
175
+
176
+ # Simulate controller receive_response
177
+ session.response = QBWC_CUSTOMER_QUERY_RESPONSE_ERROR
178
+ assert_equal 100, session.progress
179
+
180
+ # Simulate controller send_request
181
+ assert_nil session.next_request
182
+
183
+ # Simulate controller get_last_error
184
+ session = QBWC::ActiveRecord::Session.get(ticket_string) # simulated get_session
185
+ session.save # simulated save_session
186
+
187
+ end
188
+
189
+ test "processes warning response stop" do
190
+ QBWC.on_error = :stop
191
+ QBWC.add_job(:query_joe_customer, true, COMPANY, HandleResponseWithDataWorker)
192
+ _receive_responses(WARN_RESPONSE.merge(:progress => 100))
193
+ end
194
+
195
+ test "processes warning response continue" do
196
+ QBWC.on_error = :continue
197
+ QBWC.add_job(:query_joe_customer, true, COMPANY, HandleResponseWithDataWorker)
198
+ _receive_responses(WARN_RESPONSE.merge(:progress => 100))
199
+ end
200
+
201
+ test "processes error response stop" do
202
+ QBWC.on_error = :stop
203
+ QBWC.add_job(:query_joe_customer, true, COMPANY, HandleResponseWithDataWorker)
204
+ _receive_responses(ERROR_RESPONSE.merge(:progress => 100))
205
+ end
206
+
207
+ test "processes error response continue" do
208
+ QBWC.on_error = :continue
209
+ QBWC.add_job(:query_joe_customer, true, COMPANY, HandleResponseWithDataWorker)
210
+ _receive_responses(ERROR_RESPONSE.merge(:progress => 100))
211
+ end
212
+
213
+ class MultiRequestWorker < QBWC::Worker
214
+ def requests(job)
215
+ [
216
+ {:customer_query_rq => {:full_name => 'First Request'}},
217
+ {:customer_query_rq => {:full_name => 'Second Request'}},
218
+ ]
219
+ end
220
+ def handle_response(resp, session, job, request, data)
221
+ $HANDLE_RESPONSE_EXECUTED = true
222
+ end
223
+ end
224
+
225
+ test "processes warning then error stop 2jobs" do
226
+ QBWC.on_error = :stop
227
+ QBWC.add_job(:query_joe_customer, true, COMPANY, HandleResponseWithDataWorker)
228
+ QBWC.add_job(:query_joe_customer_again, true, COMPANY, HandleResponseWithDataWorker)
229
+
230
+ _test_warning_then_error
231
+ end
232
+
233
+ test "processes warning then error continue 2jobs" do
234
+ QBWC.on_error = :continue
235
+ QBWC.add_job(:query_joe_customer, true, COMPANY, HandleResponseWithDataWorker)
236
+ QBWC.add_job(:query_joe_customer_again, true, COMPANY, HandleResponseWithDataWorker)
237
+
238
+ _test_warning_then_error
239
+ end
240
+
241
+ test "processes warning then error stop 2requests byworker" do
242
+ QBWC.on_error = :stop
243
+ QBWC.add_job(:multiple_request_job, true, COMPANY, MultiRequestWorker)
244
+ _test_warning_then_error(0)
245
+ end
246
+
247
+ test "processes warning then error continue 2requests byworker" do
248
+ QBWC.on_error = :continue
249
+ QBWC.add_job(:multiple_request_job, true, COMPANY, MultiRequestWorker)
250
+ _test_warning_then_error(0)
251
+ end
252
+
253
+ test "processes warning then error stop 2requests byargument" do
254
+ QBWC.on_error = :stop
255
+ QBWC.add_job(:multiple_request_job, true, COMPANY, HandleResponseWithDataWorker, [QBWC_CUSTOMER_QUERY_RQ, QBWC_CUSTOMER_QUERY_RQ])
256
+ _test_warning_then_error(0)
257
+ end
258
+
259
+ test "processes warning then error continue 2requests byargument" do
260
+ QBWC.on_error = :continue
261
+ QBWC.add_job(:multiple_request_job, true, COMPANY, HandleResponseWithDataWorker, [QBWC_CUSTOMER_QUERY_RQ, QBWC_CUSTOMER_QUERY_RQ])
262
+ _test_warning_then_error(0)
263
+ end
264
+
265
+ test "processes error then warning stop 2jobs" do
266
+ QBWC.on_error = :stop
267
+ QBWC.add_job(:query_joe_customer, true, COMPANY, HandleResponseWithDataWorker)
268
+ QBWC.add_job(:query_joe_customer_again, true, COMPANY, HandleResponseWithDataWorker)
269
+ _test_error_then_warning_that_stops
270
+ end
271
+
272
+ test "processes error then warning continue 2jobs" do
273
+ QBWC.on_error = :continue
274
+ QBWC.add_job(:query_joe_customer, true, COMPANY, HandleResponseWithDataWorker)
275
+ QBWC.add_job(:query_joe_customer_again, true, COMPANY, HandleResponseWithDataWorker)
276
+ _test_error_then_warning
277
+ end
278
+
279
+ test "processes error then warning stop 2requests byworker" do
280
+ QBWC.on_error = :stop
281
+ QBWC.add_job(:multiple_request_job, true, COMPANY, MultiRequestWorker)
282
+ _test_error_then_warning_that_stops
283
+ end
284
+
285
+ test "processes error then warning continue 2requests byworker" do
286
+ QBWC.on_error = :continue
287
+ QBWC.add_job(:multiple_request_job, true, COMPANY, MultiRequestWorker)
288
+ _test_error_then_warning(0)
289
+ end
290
+
291
+ test "processes error then warning stop 2requests byargument" do
292
+ QBWC.on_error = :stop
293
+ QBWC.add_job(:multiple_request_job, true, COMPANY, HandleResponseWithDataWorker, [QBWC_CUSTOMER_QUERY_RQ, QBWC_CUSTOMER_QUERY_RQ])
294
+ _test_error_then_warning_that_stops
295
+ end
296
+
297
+ test "processes error then warning continue 2requests byargument" do
298
+ QBWC.on_error = :continue
299
+ QBWC.add_job(:multiple_request_job, true, COMPANY, HandleResponseWithDataWorker, [QBWC_CUSTOMER_QUERY_RQ, QBWC_CUSTOMER_QUERY_RQ])
300
+ _test_error_then_warning(0)
301
+ end
302
+
303
+ end
@@ -0,0 +1,38 @@
1
+ $:<< File.expand_path(File.dirname(__FILE__) + '/../..')
2
+ require 'test_helper.rb'
3
+
4
+ class RoutesTest < ActionDispatch::IntegrationTest
5
+
6
+ def setup
7
+ RoutesTest.app = Rails.application
8
+
9
+ # Initialize sets view paths
10
+ RoutesTest.app.initialize! unless RoutesTest.app.initialized?
11
+
12
+ # Assign routes
13
+ QbwcTestApplication::Application.routes.draw do
14
+ _assign_routes
15
+ end
16
+
17
+ QBWC.clear_jobs
18
+ end
19
+
20
+ test "qwc" do
21
+ #_inspect_routes
22
+ get '/qbwc/qwc'
23
+
24
+ assert_match /QBWCXML/, @response.body
25
+ assert_match Regexp.new("AppName.*QbwcTestApplication #{Rails.env}.*AppName"), @response.body
26
+ assert_match /AppURL.*http:\/\/www.example.com\/qbwc\/action.*AppURL/, @response.body
27
+ assert_match /AppDescription.*Quickbooks integration.*AppDescription/, @response.body
28
+ assert_match /AppSupport.*https:\/\/www.example.com\/.*AppSupport/, @response.body
29
+ assert_match /UserName.*#{QBWC_USERNAME}.*UserName/, @response.body
30
+ end
31
+
32
+ test "qbwc/action without soap returns successfully" do
33
+ #_inspect_routes
34
+ get '/qbwc/action'
35
+ assert_response :success
36
+ end
37
+
38
+ end
@@ -0,0 +1,94 @@
1
+ $:<< File.expand_path(File.dirname(__FILE__) + '/../..')
2
+ require 'test_helper.rb'
3
+
4
+ class SessionTest < ActionDispatch::IntegrationTest
5
+
6
+ def setup
7
+ SessionTest.app = Rails.application
8
+ QBWC.clear_jobs
9
+ end
10
+
11
+ class ProgressTestWorker < QBWC::Worker
12
+ def requests(job)
13
+ {:customer_query_rq => {:full_name => 'Quincy Bob William Carlos'}}
14
+ end
15
+ end
16
+
17
+ test "progress increments when worker determines requests" do
18
+
19
+ # Add two jobs
20
+ QBWC.add_job(:session_test_1, true, COMPANY, ProgressTestWorker)
21
+ QBWC.add_job(:session_test_2, true, COMPANY, ProgressTestWorker)
22
+
23
+ assert_equal 2, QBWC.jobs.count
24
+ assert_equal 2, QBWC.pending_jobs(COMPANY).count
25
+
26
+ session = QBWC::Session.new(nil, COMPANY)
27
+
28
+ # Simulate controller 1st send_request and receive_response
29
+ request = session.current_request
30
+ session.response = QBWC_CUSTOMER_QUERY_RESPONSE_INFO
31
+ assert_equal 50, session.progress
32
+
33
+ # Simulate controller 2nd send_request and receive_response
34
+ request = session.current_request
35
+ session.response = QBWC_CUSTOMER_QUERY_RESPONSE_INFO
36
+ assert_equal 100, session.progress
37
+ end
38
+
39
+ test "progress increments when passing requests" do
40
+
41
+ # Add two jobs
42
+ QBWC.add_job(:session_test_1, true, COMPANY, QBWC::Worker, QBWC_CUSTOMER_ADD_RQ)
43
+ QBWC.add_job(:session_test_2, true, COMPANY, QBWC::Worker, QBWC_CUSTOMER_QUERY_RQ)
44
+
45
+ assert_equal 2, QBWC.jobs.count
46
+ assert_equal 2, QBWC.pending_jobs(COMPANY).count
47
+
48
+ session = QBWC::Session.new(nil, COMPANY)
49
+
50
+ # Simulate controller 1st send_request and receive_response
51
+ request = session.current_request
52
+ session.response = QBWC_CUSTOMER_ADD_RESPONSE_LONG
53
+ assert_equal 50, session.progress
54
+
55
+ # Simulate controller 2nd send_request and receive_response
56
+ request = session.current_request
57
+ session.response = QBWC_CUSTOMER_QUERY_RESPONSE_INFO
58
+ assert_equal 100, session.progress
59
+ end
60
+
61
+ test "sends request only once when passing requests to add_job" do
62
+
63
+ # Add a job and pass a request
64
+ QBWC.add_job(:add_joe_customer, true, COMPANY, QBWC::Worker, QBWC_CUSTOMER_ADD_RQ_LONG)
65
+
66
+ assert_equal 1, QBWC.jobs.count
67
+ assert_equal 1, QBWC.pending_jobs(COMPANY).count
68
+
69
+ # Omit these controller calls that normally occur during a QuickBooks Web Connector session:
70
+ # - server_version
71
+ # - client_version
72
+ # - authenticate
73
+ # - send_request
74
+
75
+ # Simulate controller receive_response
76
+ session = QBWC::Session.new(nil, COMPANY)
77
+ session.response = QBWC_CUSTOMER_ADD_RESPONSE_LONG
78
+
79
+ assert_equal 100, session.progress
80
+ end
81
+
82
+ test "request_to_send when no requests" do
83
+
84
+ QBWC.add_job(:add_joe_customer, true, COMPANY, QBWC::Worker, [])
85
+
86
+ assert_equal 1, QBWC.jobs.count
87
+ assert_equal 1, QBWC.pending_jobs(COMPANY).count
88
+
89
+ # Simulate controller send_request
90
+ session = QBWC::Session.new(nil, COMPANY)
91
+ request = session.request_to_send
92
+ end
93
+
94
+ end
@@ -0,0 +1,248 @@
1
+ # http://stackoverflow.com/a/4402193
2
+ require 'bundler/setup'
3
+ Bundler.setup
4
+
5
+ require 'minitest/autorun'
6
+
7
+ require 'active_support'
8
+ require 'active_record'
9
+ require 'action_controller'
10
+ require 'rails'
11
+
12
+ $:<< File.expand_path(File.dirname(__FILE__) + '/../lib')
13
+ require 'qbwc'
14
+ require 'qbwc/controller'
15
+ require 'qbwc/active_record'
16
+
17
+ COMPANY = 'c:\\QuickBooks\MyFile.QBW'
18
+ QBWC_USERNAME = 'myUserName'
19
+ QBWC_PASSWORD = 'myPassword'
20
+ QBWC.api = :qb
21
+
22
+ ActiveSupport::TestCase.test_order = :random if defined? ActiveSupport::TestCase.test_order=()
23
+
24
+ #-------------------------------------------
25
+ # http://coryforsyth.com/2013/06/02/programmatically-list-routespaths-from-inside-your-rails-app/
26
+ def _inspect_routes
27
+ puts "\nRoutes:"
28
+ Rails.application.routes.routes.each do |route|
29
+ puts " Name #{route.name}: \t #{route.verb.source.gsub(/[$^]/, '')} #{route.path.spec.to_s}"
30
+ end
31
+ puts "\n"
32
+ end
33
+
34
+ #-------------------------------------------
35
+ # Stub Rails application
36
+ module QbwcTestApplication
37
+ class Application < Rails::Application
38
+ Rails.application.configure do
39
+ config.secret_key_base = "stub"
40
+ config.eager_load = false
41
+ end
42
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
43
+ require '../qbwc/lib/generators/qbwc/install/templates/db/migrate/create_qbwc_jobs'
44
+ require '../qbwc/lib/generators/qbwc/install/templates/db/migrate/create_qbwc_sessions'
45
+ ActiveRecord::Migration.run(CreateQbwcJobs)
46
+ ActiveRecord::Migration.run(CreateQbwcSessions)
47
+ QBWC.configure do |c|
48
+ c.username = QBWC_USERNAME
49
+ c.password = QBWC_PASSWORD
50
+ c.company_file_path = COMPANY
51
+ c.session_initializer = Proc.new{|session| $CONFIG_SESSION_INITIALIZER_PROC_EXECUTED = true }
52
+ end
53
+
54
+ # Logger
55
+ Rails.logger = Logger.new('/dev/null') # or STDOUT
56
+ QBWC.logger = Rails.logger
57
+ end
58
+
59
+ end
60
+
61
+ def _assign_routes
62
+
63
+ # Manually stub these generated routes:
64
+ # GET /qbwc/action(.:format) qbwc#_generate_wsdl
65
+ # qbwc_qwc GET /qbwc/qwc(.:format) qbwc#qwc
66
+ get 'qbwc/action' => 'qbwc#_generate_wsdl'
67
+ get 'qbwc/qwc' => 'qbwc#qwc', :as => :qbwc_qwc
68
+
69
+ # Add these routes:
70
+ # qbwc_wsdl GET /qbwc/wsdl qbwc#_generate_wsdl
71
+ # qbwc_action GET|POST /qbwc/action #<WashOut::Router:0x00000005cf46d0 @controller_name="QbwcController">
72
+ wash_out :qbwc
73
+
74
+ # Route needed for test_qwc
75
+ get 'qbwc/action' => 'qbwc#action'
76
+
77
+ get 'qbwc/authenticate' => 'qbwc#authenticate'
78
+
79
+ # Stub a root route
80
+ root :to => "qbwc#qwc"
81
+ end
82
+
83
+ QbwcTestApplication::Application.routes.draw do
84
+ _assign_routes
85
+ end
86
+
87
+ class QbwcController < ActionController::Base
88
+ include Rails.application.routes.url_helpers
89
+ include QBWC::Controller
90
+ end
91
+
92
+ QBWC_EMPTY_RESPONSE = "<?xml version=\"1.0\"?>\r
93
+ <?qbxml version=\"7.0\"?>\r
94
+ <QBXML>\r
95
+ <QBXMLMsgsRs onError=\"stopOnError\">\r
96
+ </QBXMLMsgsRs>\r
97
+ </QBXML>\r"
98
+
99
+ QBWC_CUSTOMER_ADD_RQ = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r
100
+ <?qbxml version=\"7.0\"?>\r
101
+ <QBXML>\r
102
+ <QBXMLMsgsRq onError = \"stopOnError\">\r
103
+ <CustomerAddRq>\r
104
+ <CustomerAdd>\r
105
+ <Name>#{QBWC_USERNAME}</Name>\r
106
+ </CustomerAdd>\r
107
+ </CustomerAddRq>\r
108
+ </QBXMLMsgsRq>\r
109
+ </QBXML>\r"
110
+
111
+ QBWC_CUSTOMER_ADD_RQ_LONG = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r
112
+ <?qbxml version=\"7.0\"?>\r
113
+ <QBXML>\r
114
+ <QBXMLMsgsRq onError = \"stopOnError\">\r
115
+ <CustomerAddRq>\r
116
+ <CustomerAdd>\r
117
+ <Name>mrjoecustomer</Name>\r
118
+ <IsActive>1</IsActive>\r
119
+ <CompanyName>Joes Garage</CompanyName>\r
120
+ <Salutation>Mr</Salutation>\r
121
+ <FirstName>Joe</FirstName>\r
122
+ <LastName>Customer</LastName>\r
123
+ <BillAddress>\r
124
+ <Addr1>123 Main St.</Addr1>\r
125
+ <City>Mountain View</City>\r
126
+ <State>CA</State>\r
127
+ <PostalCode>94566</PostalCode>\r
128
+ </BillAddress>\r
129
+ <Email>joecustomer@gmail.com</Email>\r
130
+ <AccountNumber>89087</AccountNumber>\r
131
+ <CreditLimit>2000.00</CreditLimit>\r
132
+ </CustomerAdd>\r
133
+ </CustomerAddRq>\r
134
+ </QBXMLMsgsRq>\r
135
+ </QBXML>\r"
136
+
137
+ QBWC_CUSTOMER_ADD_RESPONSE_LONG = "<?xml version=\"1.0\" ?><QBXML><QBXMLMsgsRs><CustomerAddRs statusCode=\"0\" statusSeverity=\"Info\" statusMessage=\"Status OK\"><CustomerRet><ListID>8000001B-1405768916</ListID><TimeCreated>2014-07-19T07:21:56-05:00</TimeCreated><TimeModified>2014-07-19T07:21:56-05:00</TimeModified><EditSequence>1405768916</EditSequence><Name>mrjoecustomer</Name><FullName>Joseph Customer</FullName><IsActive>true</IsActive><Sublevel>0</Sublevel><CompanyName>Joes Garage</CompanyName><Salutation>Mr</Salutation><FirstName>Joe</FirstName><LastName>Customer</LastName><BillAddress><Addr1>123 Main St.</Addr1><City>Mountain View</City><State>CA</State><PostalCode>94566</PostalCode></BillAddress><Email>joecustomer@gmail.com</Email><Balance>0.00</Balance><TotalBalance>0.00</TotalBalance><AccountNumber>89087</AccountNumber><CreditLimit>2000.00</CreditLimit><JobStatus>None</JobStatus></CustomerRet></CustomerAddRs></QBXMLMsgsRs></QBXML>"
138
+
139
+ QBWC_CUSTOMER_QUERY_RQ = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r
140
+ <?qbxml version=\"7.0\"?>\r
141
+ <QBXML>\r
142
+ <QBXMLMsgsRq onError = \"stopOnError\">\r
143
+ <CustomerQueryRq>\r
144
+ <FullName>#{QBWC_USERNAME}</FullName>\r
145
+ </CustomerQueryRq>\r
146
+ </QBXMLMsgsRq>\r
147
+ </QBXML>\r"
148
+
149
+ QBWC_CUSTOMER_QUERY_RESPONSE_INFO = "<?xml version=\"1.0\" ?><QBXML><QBXMLMsgsRs><CustomerQueryRs statusCode=\"0\" statusSeverity=\"Info\" statusMessage=\"Status OK\"><CustomerRet><ListID>8000001B-1405777862</ListID><TimeCreated>2014-07-30T21:11:20-05:00</TimeCreated><TimeModified>2005-07-30T21:11:20-05:00</TimeModified><EditSequence>1405777862</EditSequence><Name>#{QBWC_USERNAME}</Name><Salutation>Mr</Salutation><FullName>#{QBWC_USERNAME}</FullName><IsActive>true</IsActive><Sublevel>0</Sublevel><Email>#{QBWC_USERNAME}@gmail.com</Email><Balance>0.00</Balance><TotalBalance>0.00</TotalBalance><AccountNumber>123456789</AccountNumber><JobStatus>None</JobStatus></CustomerRet></CustomerQueryRs></QBXMLMsgsRs></QBXML>"
150
+
151
+ QBWC_CUSTOMER_QUERY_STATUS_MESSAGE_WARN = 'The query request has not been fully completed. There was a required element ("bleech") that could not be found in QuickBooks.'
152
+
153
+ QBWC_CUSTOMER_QUERY_RESPONSE_WARN = "<?xml version=\"1.0\" ?><QBXML><QBXMLMsgsRs><CustomerQueryRs statusCode=\"500\" statusSeverity=\"Warn\" statusMessage=\"The query request has not been fully completed. There was a required element (&quot;bleech&quot;) that could not be found in QuickBooks.\" /></QBXMLMsgsRs></QBXML>"
154
+
155
+ QBWC_CUSTOMER_QUERY_STATUS_MESSAGE_ERROR = 'Object "8000001B-1405768916" specified in the request cannot be found. QuickBooks error message: Invalid argument. The specified record does not exist in the list.'
156
+
157
+ QBWC_CUSTOMER_QUERY_RESPONSE_ERROR = "<?xml version=\"1.0\" ?><QBXML><QBXMLMsgsRs><CustomerQueryRs statusCode=\"3120\" statusSeverity=\"Error\" statusMessage=\"Object &quot;8000001B-1405768916&quot; specified in the request cannot be found. QuickBooks error message: Invalid argument. The specified record does not exist in the list.\" /></QBXMLMsgsRs></QBXML>"
158
+
159
+ AUTHENTICATE_PARAMS = {
160
+ :strUserName => QBWC_USERNAME,
161
+ :strPassword => QBWC_PASSWORD,
162
+ :@xmlns => "http://developer.intuit.com/"
163
+ }
164
+
165
+ AUTHENTICATE_SOAP_ACTION = :authenticate
166
+ AUTHENTICATE_WASH_OUT_SOAP_DATA = {
167
+ :Envelope => {
168
+ :Body => { AUTHENTICATE_SOAP_ACTION => AUTHENTICATE_PARAMS },
169
+ :"@xmlns:soap" => "http://schemas.xmlsoap.org/soap/envelope/",
170
+ :"@xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
171
+ :"@xmlns:xsd" => "http://www.w3.org/2001/XMLSchema"
172
+ }
173
+ }
174
+
175
+ SEND_REQUEST_PARAMS = {
176
+ :qbXMLCountry => "US",
177
+ :qbXMLMajorVers => "13",
178
+ :qbXMLMinorVers => "0",
179
+ :ticket => "acc277c2d9351c6da12345887293fc6a32860006",
180
+ :strHCPResponse => "<?xml version=\"1.0\" ?><QBXML><QBXMLMsgsRs><HostQueryRs requestID=\"0\" statusCode=\"0\" statusSeverity=\"Info\" statusMessage=\"Status OK\"><HostRet><ProductName>QuickBooks Pro 2014</ProductName><MajorVersion>24</MajorVersion><MinorVersion>0</MinorVersion><Country>US</Country><SupportedQBXMLVersion>1.0</SupportedQBXMLVersion><SupportedQBXMLVersion>1.1</SupportedQBXMLVersion><SupportedQBXMLVersion>2.0</SupportedQBXMLVersion><SupportedQBXMLVersion>2.1</SupportedQBXMLVersion><SupportedQBXMLVersion>3.0</SupportedQBXMLVersion><SupportedQBXMLVersion>4.0</SupportedQBXMLVersion><SupportedQBXMLVersion>4.1</SupportedQBXMLVersion><SupportedQBXMLVersion>5.0</SupportedQBXMLVersion><SupportedQBXMLVersion>6.0</SupportedQBXMLVersion><SupportedQBXMLVersion>7.0</SupportedQBXMLVersion><SupportedQBXMLVersion>8.0</SupportedQBXMLVersion><SupportedQBXMLVersion>9.0</SupportedQBXMLVersion><SupportedQBXMLVersion>10.0</SupportedQBXMLVersion><SupportedQBXMLVersion>11.0</SupportedQBXMLVersion><SupportedQBXMLVersion>12.0</SupportedQBXMLVersion><SupportedQBXMLVersion>13.0</SupportedQBXMLVersion><IsAutomaticLogin>false</IsAutomaticLogin><QBFileMode>SingleUser</QBFileMode></HostRet></HostQueryRs><CompanyQueryRs requestID=\"1\" statusCode=\"0\" statusSeverity=\"Info\" statusMessage=\"Status OK\"><CompanyRet><IsSampleCompany>false</IsSampleCompany><CompanyName>myCompany</CompanyName><LegalCompanyName>myCompany Legal Name</LegalCompanyName><Address><City>P.O. Box 12345</City><State>CA</State><PostalCode>12345</PostalCode><Country>US</Country></Address><AddressBlock><Addr1>P.O. Box 12345</Addr1><Addr2>CA 12345</Addr2></AddressBlock><LegalAddress><Addr1>P.O. Box 12345</Addr1><City>Anytown</City><State>CA</State><PostalCode>12345</PostalCode><Country>US</Country></LegalAddress><Phone>800-123-4567</Phone><Email>myname@mydomain.com</Email><FirstMonthFiscalYear>January</FirstMonthFiscalYear><FirstMonthIncomeTaxYear>January</FirstMonthIncomeTaxYear><CompanyType>InformationTechnologyComputersSoftware</CompanyType><EIN>12-3456789</EIN><TaxForm>Form1120</TaxForm><SubscribedServices><Service><Name>QuickBooks Online Banking</Name><Domain>banking.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Online Billing</Name><Domain>billing.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Online Billing Level 1 Service</Name><Domain>qbob1.qbn</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Online Billing Level 2 Service</Name><Domain>qbob2.qbn</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Online Billing Payment Service</Name><Domain>qbobpay.qbn</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Bill Payment</Name><Domain>billpay.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Online Billing Paper Mailing Service</Name><Domain>qbobpaper.qbn</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Payroll Service</Name><Domain>payroll.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Basic Payroll Service</Name><Domain>payrollbsc.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Basic Disk Payroll Service</Name><Domain>payrollbscdisk.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Deluxe Payroll Service</Name><Domain>payrolldlx.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>QuickBooks Premier Payroll Service</Name><Domain>payrollprm.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>Basic Plus Federal</Name><Domain>basic_plus_fed.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>Basic Plus Federal and State</Name><Domain>basic_plus_fed_state.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>Basic Plus Direct Deposit</Name><Domain>basic_plus_dd.qb</Domain><ServiceStatus>Never</ServiceStatus></Service><Service><Name>Merchant Account Service</Name><Domain>mas.qbn</Domain><ServiceStatus>Never</ServiceStatus></Service></SubscribedServices><AccountantCopy><AccountantCopyExists>false</AccountantCopyExists></AccountantCopy><DataExtRet><OwnerID>{512349B1-1111-2222-3333-000DE1813D20}</OwnerID><DataExtName>AppLock</DataExtName><DataExtType>STR255TYPE<yzer/DataExtType><DataExtValue>LOCKED:REDACTED:631234599990000223</DataExtValue></DataExtRet><DataExtRet><OwnerID>{512349B1-1111-2222-3333-000DE1813D20}</OwnerID><DataExtName>FileID</DataExtName><DataExtType>STR255TYPE</DataExtType><DataExtValue>{00000ee-1111-ffff-cccc-5ff123456047}</DataExtValue></DataExtRet></CompanyRet></CompanyQueryRs><PreferencesQueryRs requestID=\"2\" statusCode=\"0\" statusSeverity=\"Info\" statusMessage=\"Status OK\"><PreferencesRet><AccountingPreferences><IsUsingAccountNumbers>false</IsUsingAccountNumbers><IsRequiringAccounts>true</IsRequiringAccounts><IsUsingClassTracking>false</IsUsingClassTracking><IsUsingAuditTrail>true</IsUsingAuditTrail><IsAssigningJournalEntryNumbers>true</IsAssigningJournalEntryNumbers></AccountingPreferences><FinanceChargePreferences><AnnualInterestRate>0.00</AnnualInterestRate><MinFinanceCharge>0.00</MinFinanceCharge><GracePeriod>0</GracePeriod><IsAssessingForOverdueCharges>false</IsAssessingForOverdueCharges><CalculateChargesFrom>DueDate</CalculateChargesFrom><IsMarkedToBePrinted>false</IsMarkedToBePrinted></FinanceChargePreferences><JobsAndEstimatesPreferences><IsUsingEstimates>true</IsUsingEstimates><IsUsingProgressInvoicing>false</IsUsingProgressInvoicing><IsPrintingItemsWithZeroAmounts>false</IsPrintingItemsWithZeroAmounts></JobsAndEstimatesPreferences><MultiCurrencyPreferences><IsMultiCurrencyOn>false</IsMultiCurrencyOn></MultiCurrencyPreferences><MultiLocationInventoryPreferences><IsMultiLocationInventoryAvailable>false</IsMultiLocationInventoryAvailable><IsMultiLocationInventoryEnabled>false</IsMultiLocationInventoryEnabled></MultiLocationInventoryPreferences><PurchasesAndVendorsPreferences><IsUsingInventory>false</IsUsingInventory><DaysBillsAreDue>10</DaysBillsAreDue><IsAutomaticallyUsingDiscounts>false</IsAutomaticallyUsingDiscounts></PurchasesAndVendorsPreferences><ReportsPreferences><AgingReportBasis>AgeFromDueDate</AgingReportBasis><SummaryReportBasis>Accrual</SummaryReportBasis></ReportsPreferences><SalesAndCustomersPreferences><IsTrackingReimbursedExpensesAsIncome>false</IsTrackingReimbursedExpensesAsIncome><IsAutoApplyingPayments>true</IsAutoApplyingPayments><PriceLevels><IsUsingPriceLevels>true</IsUsingPriceLevels><IsRoundingSalesPriceUp>true</IsRoundingSalesPriceUp></PriceLevels></SalesAndCustomersPreferences><TimeTrackingPreferences><FirstDayOfWeek>Monday</FirstDayOfWeek></TimeTrackingPreferences><CurrentAppAccessRights><IsAutomaticLoginAllowed>false</IsAutomaticLoginAllowed><IsPersonalDataAccessAllowed>false</IsPersonalDataAccessAllowed></CurrentAppAccessRights><ItemsAndInventoryPreferences><EnhancedInventoryReceivingEnabled>false</EnhancedInventoryReceivingEnabled><IsTrackingSerialOrLotNumber>None</IsTrackingSerialOrLotNumber><FIFOEnabled>false</FIFOEnabled><IsRSBEnabled>false</IsRSBEnabled><IsBarcodeEnabled>false</IsBarcodeEnabled></ItemsAndInventoryPreferences></PreferencesRet></PreferencesQueryRs></QBXMLMsgsRs></QBXML>",
181
+ }
182
+
183
+ SEND_REQUEST_SOAP_ACTION = :sendRequestXML
184
+
185
+
186
+ RECEIVE_RESPONSE_PARAMS = {
187
+ :ticket => "60676ae302a35ead77c81b16993ef073ff3c930e",
188
+ :response => "<?xml version=\"1.0\" ?><QBXML><QBXMLMsgsRs><CustomerAddRs statusCode=\"0\" statusSeverity=\"Info\" statusMessage=\"Status OK\"><CustomerRet><ListID>8000007B-1420967073</ListID><TimeCreated>2015-02-03T07:49:33-05:00</TimeCreated><TimeModified>2015-02-03T07:49:33-05:00</TimeModified><EditSequence>1420967073</EditSequence><Name>mrjoecustomer</Name><FullName>Joseph Customer</FullName><IsActive>true</IsActive><Sublevel>0</Sublevel><Email>joecustomer@gmail.com</Email><Balance>0.00</Balance><TotalBalance>0.00</TotalBalance><AccountNumber>8</AccountNumber><JobStatus>None</JobStatus></CustomerRet></CustomerAddRs></QBXMLMsgsRs></QBXML>",
189
+ :hresult => nil,
190
+ :message => nil}
191
+
192
+ RECEIVE_RESPONSE_ERROR_PARAMS = {
193
+ :ticket => "40fddf910fa903bde3caee77da7b30ab0bc90804",
194
+ :response => nil,
195
+ :hresult => "0x80040400",
196
+ :message => "QuickBooks found an error when parsing the provided XML text stream."
197
+ }
198
+
199
+ RECEIVE_RESPONSE_SOAP_ACTION = :receiveResponseXML
200
+
201
+ #-------------------------------------------
202
+ def _simulate_soap_request(http_action, soap_action, soap_params)
203
+
204
+ ticket = QBWC::ActiveRecord::Session::QbwcSession.first.ticket
205
+ wash_out_soap_data = { :Envelope => { :Body => { soap_action => soap_params.update(:ticket => ticket) }}}
206
+
207
+ # http://twobitlabs.com/2010/09/setting-request-headers-in-rails-functional-tests/
208
+ @request.env["wash_out.soap_action"] = soap_action.to_s
209
+ @request.env["wash_out.soap_data"] = wash_out_soap_data
210
+ @controller.env["wash_out.soap_data"] = @request.env["wash_out.soap_data"]
211
+
212
+ post http_action, use_route: :qbwc_action
213
+ end
214
+
215
+ #-------------------------------------------
216
+ def _authenticate
217
+ # http://twobitlabs.com/2010/09/setting-request-headers-in-rails-functional-tests/
218
+ @request.env["wash_out.soap_action"] = AUTHENTICATE_SOAP_ACTION.to_s
219
+ @request.env["wash_out.soap_data"] = AUTHENTICATE_WASH_OUT_SOAP_DATA
220
+ @controller.env["wash_out.soap_data"] = @request.env["wash_out.soap_data"]
221
+
222
+ process(:authenticate)
223
+ end
224
+
225
+ #-------------------------------------------
226
+ def _authenticate_with_queued_job
227
+ # Queue a job
228
+ QBWC.add_job(:customer_add_rq_job, true, COMPANY, QBWC::Worker)
229
+
230
+ _authenticate
231
+ end
232
+
233
+ #-------------------------------------------
234
+ def _authenticate_wrong_password
235
+ # deep copy
236
+ bad_password_soap_data = Marshal.load(Marshal.dump(AUTHENTICATE_WASH_OUT_SOAP_DATA))
237
+ bad_password_soap_data[:Envelope][:Body][AUTHENTICATE_SOAP_ACTION][:strPassword] = 'something wrong'
238
+ @request.env["wash_out.soap_action"] = AUTHENTICATE_SOAP_ACTION.to_s
239
+ @request.env["wash_out.soap_data"] = bad_password_soap_data
240
+ @controller.env["wash_out.soap_data"] = @request.env["wash_out.soap_data"]
241
+
242
+ process(:authenticate)
243
+ end
244
+
245
+ #-------------------------------------------
246
+ def simulate_response(session, response=QBWC_EMPTY_RESPONSE)
247
+ session.response = response
248
+ end