qbwc 0.0.5 → 0.1.0

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