rhoconnect 6.0.11 → 6.2.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.
- checksums.yaml +4 -4
- data/Gemfile +14 -11
- data/Gemfile.lock +120 -87
- data/Rakefile +4 -3
- data/bin/rhoconnect +0 -0
- data/bin/rhoconnect-benchmark +0 -0
- data/commands/dtach/dtach_install.rb +29 -24
- data/commands/rhoconnect/start.rb +5 -4
- data/generators/templates/application/rcgemfile +1 -1
- data/lib/rhoconnect/model/helpers/find_duplicates_on_update.rb +1 -1
- data/lib/rhoconnect/store.rb +3 -3
- data/lib/rhoconnect/version.rb +1 -1
- data/rhoconnect.gemspec +11 -11
- data/spec/api/client/get_client_params_spec.rb +4 -0
- data/spec/apps/rhotestapp/models/ruby/sample_adapter.rb +1 -1
- data/spec/client_sync_spec.rb +7 -7
- data/spec/dynamic_adapter_spec.rb +13 -13
- data/spec/generator/generator_spec.rb +7 -7
- data/spec/jobs/ping_job_spec.rb +162 -79
- data/spec/perf/perf_spec_helper.rb +5 -5
- data/spec/ping/apple_spec.rb +24 -26
- data/spec/ping/gcm_spec.rb +26 -28
- data/spec/ping/rhoconnect_push_spec.rb +13 -13
- data/spec/rhoconnect_spec.rb +2 -2
- data/spec/server/cors_spec.rb +22 -22
- data/spec/server/server_spec.rb +308 -310
- data/spec/server/stats_spec.rb +7 -7
- data/spec/server/x_domain_session_wrapper_spec.rb +40 -40
- data/spec/source_adapter_spec.rb +2 -2
- data/spec/source_sync_spec.rb +4 -4
- data/spec/spec_helper.rb +8 -8
- data/spec/stats/record_spec.rb +7 -7
- data/spec/store_orm_spec.rb +97 -94
- data/spec/store_spec.rb +23 -23
- data/spec/user_spec.rb +3 -3
- metadata +32 -26
@@ -41,12 +41,12 @@ def generate_fake_data(num=1000,unique=false)
|
|
41
41
|
unique_prefix = "#{n}-#{Time.now.to_s}"
|
42
42
|
end
|
43
43
|
res[n.to_s] = {
|
44
|
-
"FirstName" =>
|
45
|
-
"LastName" =>
|
46
|
-
"Email" =>
|
47
|
-
"Company" =>
|
44
|
+
"FirstName" => FFaker::Name.first_name + unique_prefix,
|
45
|
+
"LastName" => FFaker::Name.last_name + unique_prefix,
|
46
|
+
"Email" => FFaker::Internet.free_email + unique_prefix,
|
47
|
+
"Company" => FFaker::Company.name + unique_prefix,
|
48
48
|
"JobTitle" => title + unique_prefix,
|
49
|
-
"Phone1" =>
|
49
|
+
"Phone1" => FFaker::PhoneNumber.phone_number + unique_prefix
|
50
50
|
}
|
51
51
|
end
|
52
52
|
res
|
data/spec/ping/apple_spec.rb
CHANGED
@@ -9,22 +9,22 @@ describe "Ping Apple" do
|
|
9
9
|
"vibrate" => '5', "badge" => '5', "sound" => 'hello.mp3',
|
10
10
|
"device_pin" => @c.device_pin, "device_port" => @c.device_port}
|
11
11
|
ssl_ctx = double("ssl_ctx")
|
12
|
-
ssl_ctx.
|
13
|
-
ssl_ctx.
|
14
|
-
OpenSSL::SSL::SSLContext.
|
15
|
-
OpenSSL::PKey::RSA.
|
16
|
-
OpenSSL::X509::Certificate.
|
12
|
+
allow(ssl_ctx).to receive(:key=).and_return('key')
|
13
|
+
allow(ssl_ctx).to receive(:cert=).and_return('cert')
|
14
|
+
allow(OpenSSL::SSL::SSLContext).to receive(:new).and_return(ssl_ctx)
|
15
|
+
allow(OpenSSL::PKey::RSA).to receive(:new)
|
16
|
+
allow(OpenSSL::X509::Certificate).to receive(:new)
|
17
17
|
|
18
18
|
tcp_socket = double("tcp_socket")
|
19
|
-
tcp_socket.
|
20
|
-
TCPSocket.
|
19
|
+
allow(tcp_socket).to receive(:close)
|
20
|
+
allow(TCPSocket).to receive(:new).and_return(tcp_socket)
|
21
21
|
|
22
22
|
@ssl_socket = double("ssl_socket")
|
23
|
-
@ssl_socket.
|
24
|
-
@ssl_socket.
|
25
|
-
@ssl_socket.
|
26
|
-
@ssl_socket.
|
27
|
-
OpenSSL::SSL::SSLSocket.
|
23
|
+
allow(@ssl_socket).to receive(:sync=)
|
24
|
+
allow(@ssl_socket).to receive(:connect)
|
25
|
+
allow(@ssl_socket).to receive(:write)
|
26
|
+
allow(@ssl_socket).to receive(:close)
|
27
|
+
allow(OpenSSL::SSL::SSLSocket).to receive(:new).and_return(@ssl_socket)
|
28
28
|
end
|
29
29
|
|
30
30
|
# TODO: This should really test SSLSocket.write
|
@@ -33,9 +33,7 @@ describe "Ping Apple" do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should log deprecation on iphone ping" do
|
36
|
-
Iphone.
|
37
|
-
:log
|
38
|
-
).once.with("DEPRECATION WARNING: 'iphone' is a deprecated device_type, use 'apple' instead")
|
36
|
+
expect(Iphone).to receive(:log).once.with("DEPRECATION WARNING: 'iphone' is a deprecated device_type, use 'apple' instead")
|
39
37
|
Iphone.ping(@params)
|
40
38
|
end
|
41
39
|
|
@@ -45,8 +43,8 @@ describe "Ping Apple" do
|
|
45
43
|
"do_sync"=>["SampleAdapter"]
|
46
44
|
}
|
47
45
|
apn_message = Apple.apn_message(@params)
|
48
|
-
apn_message[0, 7].inspect.gsub("\"", "").
|
49
|
-
JSON.parse(apn_message[7, apn_message.length]).
|
46
|
+
expect(apn_message[0, 7].inspect.gsub("\"", "")).to eq("\\x00\\x00 \\xAB\\xCD\\x00g")
|
47
|
+
expect(JSON.parse(apn_message[7, apn_message.length])).to eq(expected_hash)
|
50
48
|
end
|
51
49
|
|
52
50
|
it "should compute apn_message with source array" do
|
@@ -56,21 +54,21 @@ describe "Ping Apple" do
|
|
56
54
|
"do_sync"=>["SampleAdapter", "SimpleAdapter"]
|
57
55
|
}
|
58
56
|
apn_message = Apple.apn_message(@params)
|
59
|
-
apn_message[0, 7].inspect.gsub("\"", "").
|
60
|
-
JSON.parse(apn_message[7, apn_message.length]).
|
57
|
+
expect(apn_message[0, 7].inspect.gsub("\"", "")).to eq("\\x00\\x00 \\xAB\\xCD\\x00w")
|
58
|
+
expect(JSON.parse(apn_message[7, apn_message.length])).to eq(expected_hash)
|
61
59
|
end
|
62
60
|
|
63
61
|
it "should raise SocketError if socket fails" do
|
64
62
|
error = 'socket error'
|
65
|
-
@ssl_socket.
|
66
|
-
Apple.
|
67
|
-
lambda { Apple.ping(@params) }.
|
63
|
+
allow(@ssl_socket).to receive(:write).and_raise(SocketError.new(error))
|
64
|
+
expect(Apple).to receive(:log).once.with("Error while sending ping: #{error}")
|
65
|
+
expect(lambda { Apple.ping(@params) }).to raise_error(SocketError, error)
|
68
66
|
end
|
69
67
|
|
70
68
|
it "should do nothing if no cert or host or port" do
|
71
|
-
Rhoconnect::Apple.
|
72
|
-
Rhoconnect::Apple.
|
73
|
-
OpenSSL::SSL::SSLContext.
|
69
|
+
allow(Rhoconnect::Apple).to receive(:get_config).and_return({:test => {:iphonecertfile=>"none"}})
|
70
|
+
expect(Rhoconnect::Apple).to receive(:get_config).once
|
71
|
+
expect(OpenSSL::SSL::SSLContext).to receive(:new).exactly(0).times
|
74
72
|
Apple.ping(@params)
|
75
73
|
end
|
76
|
-
end
|
74
|
+
end
|
data/spec/ping/gcm_spec.rb
CHANGED
@@ -13,59 +13,57 @@ describe "Ping Android GCM" do
|
|
13
13
|
|
14
14
|
it "should ping gcm successfully" do
|
15
15
|
result = 'id=0:34234234134254%abc123\n'
|
16
|
-
@response.
|
17
|
-
@response.
|
18
|
-
@response.
|
19
|
-
@response.
|
16
|
+
allow(@response).to receive(:code).and_return(200)
|
17
|
+
allow(@response).to receive(:body).and_return(result)
|
18
|
+
allow(@response).to receive(:headers).and_return({})
|
19
|
+
allow(@response).to receive(:return!).and_return(@response)
|
20
20
|
setup_post_yield(@response)
|
21
|
-
Gcm.ping(@params).body.
|
21
|
+
expect(Gcm.ping(@params).body).to eq(result)
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should raise error on missing gcm_api_key setting" do
|
25
25
|
key = Rhoconnect.settings[:gcm_api_key].dup
|
26
26
|
Rhoconnect.settings[:gcm_api_key] = nil
|
27
|
-
lambda { Gcm.ping(@params) }.
|
28
|
-
Gcm::InvalidApiKey, 'Missing `:gcm_api_key:` option in settings/settings.yml'
|
29
|
-
)
|
27
|
+
expect(lambda { Gcm.ping(@params) }).to raise_error(Gcm::InvalidApiKey, 'Missing `:gcm_api_key:` option in settings/settings.yml')
|
30
28
|
Rhoconnect.settings[:gcm_api_key] = key
|
31
29
|
end
|
32
30
|
|
33
31
|
it "should ping gcm with 503 connection error" do
|
34
32
|
error = 'Connection refused'
|
35
|
-
@response.
|
36
|
-
RestClient.
|
37
|
-
Gcm.
|
38
|
-
lambda { Gcm.ping(@params) }.
|
33
|
+
allow(@response).to receive(:body).and_return(error)
|
34
|
+
allow(RestClient).to receive(:post).and_raise(RestClient::Exception.new(@response,503))
|
35
|
+
allow(Gcm).to receive(:log).twice
|
36
|
+
expect(lambda { Gcm.ping(@params) }).to raise_error(RestClient::Exception)
|
39
37
|
end
|
40
38
|
|
41
39
|
it "should ping gcm with 200 error message" do
|
42
40
|
error = 'Error=QuotaExceeded'
|
43
|
-
@response.
|
44
|
-
@response.
|
45
|
-
@response.
|
41
|
+
allow(@response).to receive(:code).and_return(200)
|
42
|
+
allow(@response).to receive(:body).and_return(error)
|
43
|
+
allow(@response).to receive(:headers).and_return(nil)
|
46
44
|
setup_post_yield(@response)
|
47
|
-
Gcm.
|
48
|
-
lambda { Gcm.ping(@params) }.
|
45
|
+
expect(Gcm).to receive(:log).twice
|
46
|
+
expect(lambda { Gcm.ping(@params) }).to raise_error(Gcm::GCMPingError, "GCM ping error: QuotaExceeded")
|
49
47
|
end
|
50
48
|
|
51
49
|
it "should fail to ping with bad authentication" do
|
52
50
|
error = 'Error=BadAuthentication'
|
53
|
-
@response.
|
54
|
-
@response.
|
55
|
-
@response.
|
51
|
+
allow(@response).to receive(:code).and_return(403)
|
52
|
+
allow(@response).to receive(:body).and_return(error)
|
53
|
+
allow(@response).to receive(:headers).and_return({})
|
56
54
|
setup_post_yield(@response)
|
57
|
-
Gcm.
|
58
|
-
lambda { Gcm.ping(@params) }.
|
55
|
+
expect(Gcm).to receive(:log).twice
|
56
|
+
expect(lambda { Gcm.ping(@params) }).to raise_error(
|
59
57
|
Gcm::InvalidApiKey, "Invalid GCM api key. Obtain new api key from GCM service."
|
60
58
|
)
|
61
59
|
end
|
62
60
|
|
63
61
|
it "should ping gcm with 401 error message" do
|
64
|
-
@response.
|
65
|
-
@response.
|
62
|
+
allow(@response).to receive(:code).and_return(401)
|
63
|
+
allow(@response).to receive(:body).and_return('')
|
66
64
|
setup_post_yield(@response)
|
67
|
-
Gcm.
|
68
|
-
lambda { Gcm.ping(@params) }.
|
65
|
+
expect(Gcm).to receive(:log).twice
|
66
|
+
expect(lambda { Gcm.ping(@params) }).to raise_error(
|
69
67
|
Gcm::InvalidApiKey, "Invalid GCM api key. Obtain new api key from GCM service."
|
70
68
|
)
|
71
69
|
end
|
@@ -83,7 +81,7 @@ describe "Ping Android GCM" do
|
|
83
81
|
}
|
84
82
|
actual = Gcm.gcm_message(@params)
|
85
83
|
actual['collapse_key'] = "RAND_KEY" unless actual['collapse_key'].nil?
|
86
|
-
actual.
|
84
|
+
expect(actual).to eq(expected)
|
87
85
|
end
|
88
86
|
|
89
87
|
it "should trim empty or nil params from gcm_message" do
|
@@ -93,6 +91,6 @@ describe "Ping Android GCM" do
|
|
93
91
|
"sources" => [], "message" => '', "vibrate" => '5', "sound" => 'hello.mp3'}
|
94
92
|
actual = Gcm.gcm_message(params)
|
95
93
|
actual['collapse_key'] = "RAND_KEY" unless actual['collapse_key'].nil?
|
96
|
-
actual.
|
94
|
+
expect(actual).to eq(expected)
|
97
95
|
end
|
98
96
|
end
|
@@ -13,18 +13,18 @@ describe "Ping using RhoConnect push" do
|
|
13
13
|
|
14
14
|
it "should ping rhoconnect push successfully" do
|
15
15
|
result = ''
|
16
|
-
@response.
|
17
|
-
@response.
|
18
|
-
@response.
|
19
|
-
RestClient.
|
16
|
+
allow(@response).to receive(:code).and_return(204)
|
17
|
+
allow(@response).to receive(:body).and_return(result)
|
18
|
+
allow(@response).to receive(:return!).and_return(@response)
|
19
|
+
allow(RestClient).to receive(:post).and_return(@response)
|
20
20
|
res = RhoconnectPush.ping(@params)
|
21
|
-
res.body.
|
22
|
-
res.code.
|
21
|
+
expect(res.body).to eq(result)
|
22
|
+
expect(res.code).to eq(204)
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should ping rhoconnect push with missing push_server property" do
|
26
|
-
RhoconnectPush.
|
27
|
-
lambda { RhoconnectPush.ping(@params) }.
|
26
|
+
allow(RhoconnectPush).to receive(:get_config).and_return({:test => {}})
|
27
|
+
expect(lambda { RhoconnectPush.ping(@params) }).to raise_error(
|
28
28
|
RhoconnectPush::InvalidPushServer, "Missing or invalid `:push_server` in settings/settings.yml."
|
29
29
|
)
|
30
30
|
end
|
@@ -32,11 +32,11 @@ describe "Ping using RhoConnect push" do
|
|
32
32
|
|
33
33
|
it "should ping rhoconnect push with 400 response" do
|
34
34
|
result = ''
|
35
|
-
@response.
|
36
|
-
@response.
|
37
|
-
@response.
|
35
|
+
allow(@response).to receive(:code).and_return(400)
|
36
|
+
allow(@response).to receive(:body).and_return(result)
|
37
|
+
allow(@response).to receive(:return!).and_return(@response)
|
38
38
|
setup_post_yield(@response)
|
39
|
-
lambda { RhoconnectPush.ping(@params) }.
|
39
|
+
expect(lambda { RhoconnectPush.ping(@params) }).to raise_error(
|
40
40
|
RhoconnectPush::InvalidPushRequest, "Invalid push request."
|
41
41
|
)
|
42
42
|
end
|
@@ -52,6 +52,6 @@ describe "Ping using RhoConnect push" do
|
|
52
52
|
}
|
53
53
|
}
|
54
54
|
actual = RhoconnectPush.push_message(@params)
|
55
|
-
JSON.parse(actual).
|
55
|
+
expect(JSON.parse(actual)).to eq(expected)
|
56
56
|
end
|
57
57
|
end
|
data/spec/rhoconnect_spec.rb
CHANGED
@@ -22,7 +22,7 @@ describe "Rhoconnect" do
|
|
22
22
|
Rhoconnect.environment.should == :test
|
23
23
|
Rhoconnect.stats.should == false
|
24
24
|
Rhoconnect.cookie_expire.should == 9999999
|
25
|
-
App.is_exist?(test_app_name).should
|
25
|
+
App.is_exist?(test_app_name).should be true
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should bootstrap Rhoconnect with RHO_ENV provided" do
|
@@ -69,4 +69,4 @@ describe "Rhoconnect" do
|
|
69
69
|
s = Source.load('SampleAdapter',{:app_id => test_app_name,:user_id => '*'})
|
70
70
|
s.has_many.should == "FixedSchemaAdapter,brand"
|
71
71
|
end
|
72
|
-
end
|
72
|
+
end
|
data/spec/server/cors_spec.rb
CHANGED
@@ -53,9 +53,9 @@ describe "CORS middleware" do
|
|
53
53
|
allow.resource nil, :headers => :any, :methods => [:get, :post, :put, :delete], :credentials => true
|
54
54
|
rescue Exception => e
|
55
55
|
exception_happens = true
|
56
|
-
e.is_a?(TypeError).
|
56
|
+
expect(e.is_a?(TypeError)).to be true
|
57
57
|
end
|
58
|
-
exception_happens.
|
58
|
+
expect(exception_happens).to be true
|
59
59
|
|
60
60
|
allow.resource "/*", :headers => :any, :methods => [:get, :post, :put, :delete], :credentials => true
|
61
61
|
end
|
@@ -68,8 +68,8 @@ describe "CORS middleware" do
|
|
68
68
|
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'POST'
|
69
69
|
}
|
70
70
|
status, headers, body = mv.call(env)
|
71
|
-
200.
|
72
|
-
headers['Access-Control-Allow-Origin'].
|
71
|
+
expect(200).to eq(status)
|
72
|
+
expect(headers['Access-Control-Allow-Origin']).to eq('*')
|
73
73
|
end
|
74
74
|
|
75
75
|
it "preflight check should disable unknown origins" do
|
@@ -80,8 +80,8 @@ describe "CORS middleware" do
|
|
80
80
|
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'POST'
|
81
81
|
}
|
82
82
|
status, headers, body = @middleware.call(env)
|
83
|
-
200.
|
84
|
-
headers['Access-Control-Allow-Origin'].
|
83
|
+
expect(200).to eq(status)
|
84
|
+
expect(headers['Access-Control-Allow-Origin']).not_to eq('wrong_origin')
|
85
85
|
end
|
86
86
|
|
87
87
|
it "preflight check should allow known origins" do
|
@@ -92,8 +92,8 @@ describe "CORS middleware" do
|
|
92
92
|
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'POST'
|
93
93
|
}
|
94
94
|
status, headers, body = @middleware.call(env)
|
95
|
-
200.
|
96
|
-
headers['Access-Control-Allow-Origin'].
|
95
|
+
expect(200).to eq(status)
|
96
|
+
expect(headers['Access-Control-Allow-Origin']).to eq('allowed_origin')
|
97
97
|
end
|
98
98
|
|
99
99
|
it "able to use fallback X-ORIGIN request header if ORIGIN header is undefined" do
|
@@ -104,8 +104,8 @@ describe "CORS middleware" do
|
|
104
104
|
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'POST'
|
105
105
|
}
|
106
106
|
status, headers, body = @middleware.call(env)
|
107
|
-
200.
|
108
|
-
headers['Access-Control-Allow-Origin'].
|
107
|
+
expect(200).to eq(status)
|
108
|
+
expect(headers['Access-Control-Allow-Origin']).to eq('allowed_origin')
|
109
109
|
end
|
110
110
|
|
111
111
|
it "preflight check treats empty 'null' origin as 'file://' one" do
|
@@ -116,8 +116,8 @@ describe "CORS middleware" do
|
|
116
116
|
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'POST'
|
117
117
|
}
|
118
118
|
status, headers, body = @middleware.call(env)
|
119
|
-
200.
|
120
|
-
headers['Access-Control-Allow-Origin'].
|
119
|
+
expect(200).to eq(status)
|
120
|
+
expect(headers['Access-Control-Allow-Origin']).to eq('file://')
|
121
121
|
end
|
122
122
|
|
123
123
|
it "preflight check should enable allowed request headers" do
|
@@ -129,9 +129,9 @@ describe "CORS middleware" do
|
|
129
129
|
'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' => 'allowed_header'
|
130
130
|
}
|
131
131
|
status, headers, body = @middleware.call(env)
|
132
|
-
200.
|
132
|
+
expect(200).to eq(status)
|
133
133
|
#headers['Access-Control-Allow-Origin'].should == 'allowed_origin'
|
134
|
-
headers['Access-Control-Allow-Headers'].
|
134
|
+
expect(headers['Access-Control-Allow-Headers']).to eq('allowed_header')
|
135
135
|
end
|
136
136
|
|
137
137
|
it "preflight check should disable not allowed request headers" do
|
@@ -143,9 +143,9 @@ describe "CORS middleware" do
|
|
143
143
|
'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' => 'not_allowed_header'
|
144
144
|
}
|
145
145
|
status, headers, body = @middleware.call(env)
|
146
|
-
200.
|
146
|
+
expect(200).to eq(status)
|
147
147
|
#headers['Access-Control-Allow-Origin'].should == 'allowed_origin'
|
148
|
-
headers['Access-Control-Allow-Headers'].
|
148
|
+
expect(headers['Access-Control-Allow-Headers']).not_to eq('not_allowed_header')
|
149
149
|
end
|
150
150
|
|
151
151
|
it "preflight check should allow any request headers if configured so" do
|
@@ -157,9 +157,9 @@ describe "CORS middleware" do
|
|
157
157
|
'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' => 'not_allowed_header'
|
158
158
|
}
|
159
159
|
status, headers, body = @middleware.call(env)
|
160
|
-
200.
|
160
|
+
expect(200).to eq(status)
|
161
161
|
#headers['Access-Control-Allow-Origin'].should == 'allowed_origin'
|
162
|
-
headers['Access-Control-Allow-Headers'].
|
162
|
+
expect(headers['Access-Control-Allow-Headers']).to eq('not_allowed_header')
|
163
163
|
end
|
164
164
|
|
165
165
|
|
@@ -171,8 +171,8 @@ describe "CORS middleware" do
|
|
171
171
|
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'POST'
|
172
172
|
}
|
173
173
|
status, headers, body = @middleware.call(env)
|
174
|
-
200.
|
175
|
-
headers['Access-Control-Expose-Headers'].
|
174
|
+
expect(200).to eq(status)
|
175
|
+
expect(headers['Access-Control-Expose-Headers']).to eq('Content-Length')
|
176
176
|
end
|
177
177
|
|
178
178
|
it "no response headers should be exposed by default" do
|
@@ -183,8 +183,8 @@ describe "CORS middleware" do
|
|
183
183
|
'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'POST'
|
184
184
|
}
|
185
185
|
status, headers, body = @middleware.call(env)
|
186
|
-
200.
|
187
|
-
headers['Access-Control-Expose-Headers'].
|
186
|
+
expect(200).to eq(status)
|
187
|
+
expect(headers['Access-Control-Expose-Headers']).to eq('')
|
188
188
|
end
|
189
189
|
|
190
190
|
|
data/spec/server/server_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'rack/test'
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__),'..','spec_helper')
|
4
|
-
require File.join(File.dirname(__FILE__),'..','..','lib','rhoconnect','server.rb')
|
3
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
4
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'rhoconnect', 'server.rb')
|
5
5
|
|
6
6
|
describe "Server" do
|
7
7
|
include Rack::Test::Methods
|
@@ -11,7 +11,7 @@ describe "Server" do
|
|
11
11
|
before(:each) do
|
12
12
|
Rhoconnect::Server.set :secret, "secure!"
|
13
13
|
Rhoconnect::Server.use Rack::Static, :urls => ["/data"],
|
14
|
-
|
14
|
+
:root => File.expand_path(File.join(File.dirname(__FILE__), '..', 'apps', 'rhotestapp'))
|
15
15
|
end
|
16
16
|
|
17
17
|
def app
|
@@ -20,36 +20,36 @@ describe "Server" do
|
|
20
20
|
|
21
21
|
it "should show status page" do
|
22
22
|
get '/'
|
23
|
-
last_response.status.
|
23
|
+
expect(last_response.status).to eq(302)
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should login if content-type contains extra parameters" do
|
27
|
-
post "/rc/#{Rhoconnect::API_VERSION}/system/login", {"login" => 'rhoadmin', "password" => ''}.to_json, {'CONTENT_TYPE'=>'application/json; charset=UTF-8'}
|
28
|
-
last_response.
|
27
|
+
post "/rc/#{Rhoconnect::API_VERSION}/system/login", {"login" => 'rhoadmin', "password" => ''}.to_json, {'CONTENT_TYPE' => 'application/json; charset=UTF-8'}
|
28
|
+
expect(last_response).to be_ok
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should fail to login if wrong content-type" do
|
32
|
-
post "/rc/#{Rhoconnect::API_VERSION}/system/login", {"login" => 'rhoadmin', "password" => ''}.to_json, {'CONTENT_TYPE'=>'application/x-www-form-urlencoded'}
|
33
|
-
last_response.
|
32
|
+
post "/rc/#{Rhoconnect::API_VERSION}/system/login", {"login" => 'rhoadmin', "password" => ''}.to_json, {'CONTENT_TYPE' => 'application/x-www-form-urlencoded'}
|
33
|
+
expect(last_response).not_to be_ok
|
34
34
|
end
|
35
35
|
|
36
36
|
it "should login as rhoadmin user" do
|
37
37
|
post "/rc/#{Rhoconnect::API_VERSION}/system/login", "login" => 'rhoadmin', "password" => ''
|
38
|
-
last_response.
|
38
|
+
expect(last_response).to be_ok
|
39
39
|
end
|
40
40
|
|
41
41
|
it "should respond with 404 if controller name is not specified" do
|
42
42
|
get "/app/#{Rhoconnect::API_VERSION}/"
|
43
|
-
last_response.status.
|
43
|
+
expect(last_response.status).to eq(404)
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should have default session secret" do
|
47
|
-
Rhoconnect::Server.secret.
|
47
|
+
expect(Rhoconnect::Server.secret).to eq("secure!")
|
48
48
|
end
|
49
49
|
|
50
50
|
it "should update session secret to default" do
|
51
51
|
Rhoconnect::Server.set :secret, "<changeme>"
|
52
|
-
Rhoconnect::Server.secret.
|
52
|
+
expect(Rhoconnect::Server.secret).to eq("<changeme>")
|
53
53
|
allow(Rhoconnect::Server).to receive(:log).with(any_args())
|
54
54
|
check_default_secret!("<changeme>")
|
55
55
|
Rhoconnect::Server.set :secret, "secure!"
|
@@ -62,57 +62,57 @@ describe "Server" do
|
|
62
62
|
|
63
63
|
it "should return nil if params[:source_name] is missing" do
|
64
64
|
get "/application"
|
65
|
-
last_response.status.
|
65
|
+
expect(last_response.status).to eq(500)
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
69
|
describe "auth routes" do
|
70
70
|
it "should login user with correct username,password" do
|
71
71
|
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'testpass'
|
72
|
-
last_response.
|
72
|
+
expect(last_response).to be_ok
|
73
73
|
end
|
74
74
|
|
75
75
|
it "should login user with correct username,password old route and deprecation warning" do
|
76
76
|
do_post "/application/clientlogin", "login" => @u.login, "password" => 'testpass'
|
77
|
-
last_response.
|
78
|
-
last_response.headers["Warning"].index('deprecated').
|
77
|
+
expect(last_response).to be_ok
|
78
|
+
expect(last_response.headers["Warning"].index('deprecated')).not_to be_nil
|
79
79
|
end
|
80
80
|
|
81
81
|
it "should login user with correct username,password if backend service defined" do
|
82
82
|
stub_request(:post, "http://test.com/rhoconnect/authenticate").to_return(:body => "lucas")
|
83
83
|
Rhoconnect.appserver = 'http://test.com'
|
84
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
85
|
-
last_response.
|
84
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => 'lucas', "password" => 'testpass'
|
85
|
+
expect(last_response).to be_ok
|
86
86
|
end
|
87
87
|
|
88
88
|
it "should return 401 and LoginException messsage from authenticate" do
|
89
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
90
|
-
last_response.status.
|
91
|
-
last_response.body.
|
89
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'wrongpass'
|
90
|
+
expect(last_response.status).to eq(401)
|
91
|
+
expect(last_response.body).to eq('login exception')
|
92
92
|
end
|
93
93
|
|
94
94
|
it "should return 500 and Exception messsage from authenticate" do
|
95
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
96
|
-
last_response.status.
|
97
|
-
last_response.body.
|
95
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'server error'
|
96
|
+
expect(last_response.status).to eq(500)
|
97
|
+
expect(last_response.body).to eq('server error')
|
98
98
|
end
|
99
99
|
|
100
100
|
it "should return 401 and no messsage from authenticate if no exception raised" do
|
101
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
102
|
-
last_response.status.
|
103
|
-
last_response.body.
|
101
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'wrongpassnomsg'
|
102
|
+
expect(last_response.status).to eq(401)
|
103
|
+
expect(last_response.body).to eq("Unable to authenticate '#{@u.login}'")
|
104
104
|
end
|
105
105
|
|
106
106
|
it "should create unknown user through delegated authentication" do
|
107
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
108
|
-
User.is_exist?('newuser').
|
109
|
-
@a.users.members.sort.
|
107
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => 'newuser', "password" => 'testpass'
|
108
|
+
expect(User.is_exist?('newuser')).to be true
|
109
|
+
expect(@a.users.members.sort).to eq(['newuser', 'testuser'])
|
110
110
|
end
|
111
111
|
|
112
112
|
it "should create a different username through delegated authentication" do
|
113
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
114
|
-
User.is_exist?('different').
|
115
|
-
@a.users.members.sort.
|
113
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => 'newuser', "password" => 'diffuser'
|
114
|
+
expect(User.is_exist?('different')).to be true
|
115
|
+
expect(@a.users.members.sort).to eq(['different', 'testuser'])
|
116
116
|
end
|
117
117
|
|
118
118
|
context "rps authenticate" do
|
@@ -121,7 +121,7 @@ describe "Server" do
|
|
121
121
|
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'testpass'
|
122
122
|
authorize 'rpsuser', 'secret'
|
123
123
|
get "/rc/#{Rhoconnect::API_VERSION}/app/rps_login", {}
|
124
|
-
last_response.status.
|
124
|
+
expect(last_response.status).to eq(204)
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
@@ -131,24 +131,24 @@ describe "Server" do
|
|
131
131
|
# :push_server: http://user:pwd@localhost:8675
|
132
132
|
authorize 'user', 'pwd'
|
133
133
|
get "/rc/#{Rhoconnect::API_VERSION}/system/rps_login", {}
|
134
|
-
last_response.status.
|
134
|
+
expect(last_response.status).to eq(204)
|
135
135
|
end
|
136
136
|
it "should not authenticate rhoconnect app with invalid rhoconnect push server credentials" do
|
137
137
|
authorize 'someappname', ''
|
138
138
|
get "/rc/#{Rhoconnect::API_VERSION}/system/rps_login", {}
|
139
|
-
last_response.status.
|
139
|
+
expect(last_response.status).to eq(401)
|
140
140
|
end
|
141
141
|
it "should not authenticate rhoconnect app with invalid basic Authorization header in request" do
|
142
142
|
# Basic Authorization header is missing
|
143
143
|
get "/rc/#{Rhoconnect::API_VERSION}/system/rps_login", {}
|
144
|
-
last_response.status.
|
144
|
+
expect(last_response.status).to eq(401)
|
145
145
|
end
|
146
146
|
end
|
147
147
|
end
|
148
148
|
|
149
149
|
describe "controller custom routes" do
|
150
150
|
before(:each) do
|
151
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
151
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'testpass'
|
152
152
|
end
|
153
153
|
|
154
154
|
it "should register custom_route in DefaultServer and process it" do
|
@@ -157,7 +157,7 @@ describe "Server" do
|
|
157
157
|
end
|
158
158
|
|
159
159
|
get "/my_custom_route", {}
|
160
|
-
last_response.body.
|
160
|
+
expect(last_response.body).to eq("Hello World!")
|
161
161
|
end
|
162
162
|
|
163
163
|
it "should register custom_route in SimpleAdapter controller and process it" do
|
@@ -165,7 +165,7 @@ describe "Server" do
|
|
165
165
|
"Hello World!"
|
166
166
|
end
|
167
167
|
get "/app/#{Rhoconnect::API_VERSION}/SimpleAdapter/my_custom_route", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
168
|
-
last_response.body.
|
168
|
+
expect(last_response.body).to eq("Hello World!")
|
169
169
|
end
|
170
170
|
|
171
171
|
it "should register custom_route in SimpleAdapter controller, require client condition and return error if client is missing" do
|
@@ -173,50 +173,48 @@ describe "Server" do
|
|
173
173
|
"Hello World!"
|
174
174
|
end
|
175
175
|
get "/app/#{Rhoconnect::API_VERSION}/SimpleAdapter/my_custom_route_with_client", {}
|
176
|
-
last_response.body.
|
177
|
-
last_response.status.
|
176
|
+
expect(last_response.body).to eq("Unknown client")
|
177
|
+
expect(last_response.status).to eq(500)
|
178
178
|
end
|
179
179
|
end
|
180
180
|
|
181
181
|
describe "client management routes" do
|
182
182
|
before(:each) do
|
183
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
183
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'testpass'
|
184
184
|
end
|
185
185
|
|
186
186
|
it "should respond to clientcreate" do
|
187
187
|
do_post "/rc/#{Rhoconnect::API_VERSION}/clients", 'device_type' => 'Android'
|
188
|
-
last_response.
|
189
|
-
last_response.content_type.
|
188
|
+
expect(last_response).to be_ok
|
189
|
+
expect(last_response.content_type).to match /application\/json/
|
190
190
|
id = JSON.parse(last_response.body)['client']['client_id']
|
191
|
-
id.length.
|
192
|
-
JSON.parse(last_response.body).
|
193
|
-
|
194
|
-
c
|
195
|
-
c.
|
196
|
-
c.device_type.should == 'Android'
|
191
|
+
expect(id.length).to eq(32)
|
192
|
+
expect(JSON.parse(last_response.body)).to eq({"client" => {"client_id" => id}})
|
193
|
+
c = Client.load(id, {:source_name => '*'})
|
194
|
+
expect(c.user_id).to eq('testuser')
|
195
|
+
expect(c.device_type).to eq('Android')
|
197
196
|
end
|
198
197
|
|
199
198
|
it "should respond to clientcreate with old route and deprecation warning" do
|
200
199
|
get "/application/clientcreate?device_type=Android"
|
201
|
-
last_response.
|
202
|
-
last_response.headers["Warning"].index('deprecated').
|
203
|
-
last_response.content_type.
|
200
|
+
expect(last_response).to be_ok
|
201
|
+
expect(last_response.headers["Warning"].index('deprecated')).not_to be_nil
|
202
|
+
expect(last_response.content_type).to match /application\/json/
|
204
203
|
id = JSON.parse(last_response.body)['client']['client_id']
|
205
|
-
id.length.
|
206
|
-
JSON.parse(last_response.body).
|
207
|
-
|
208
|
-
c
|
209
|
-
c.
|
210
|
-
c.device_type.should == 'Android'
|
204
|
+
expect(id.length).to eq(32)
|
205
|
+
expect(JSON.parse(last_response.body)).to eq({"client" => {"client_id" => id}})
|
206
|
+
c = Client.load(id, {:source_name => '*'})
|
207
|
+
expect(c.user_id).to eq('testuser')
|
208
|
+
expect(c.device_type).to eq('Android')
|
211
209
|
end
|
212
210
|
|
213
211
|
it "should respond to clientregister" do
|
214
212
|
do_post "/rc/#{Rhoconnect::API_VERSION}/clients/#{@c.id}/register",
|
215
|
-
|
216
|
-
last_response.
|
217
|
-
@c.device_type.
|
218
|
-
@c.device_pin.
|
219
|
-
@c.id.length.
|
213
|
+
"device_type" => "iPhone", "device_pin" => 'abcd'
|
214
|
+
expect(last_response).to be_ok
|
215
|
+
expect(@c.device_type).to eq('Apple')
|
216
|
+
expect(@c.device_pin).to eq('abcd')
|
217
|
+
expect(@c.id.length).to eq(32)
|
220
218
|
end
|
221
219
|
|
222
220
|
it "should respond to clientregister without clientcreate" do
|
@@ -224,12 +222,12 @@ describe "Server" do
|
|
224
222
|
client_id = @c.id.clone
|
225
223
|
@c = nil
|
226
224
|
do_post "/rc/#{Rhoconnect::API_VERSION}/clients/#{client_id}/register",
|
227
|
-
|
228
|
-
last_response.
|
225
|
+
"device_type" => "iPhone", "device_pin" => 'abcd'
|
226
|
+
expect(last_response).to be_ok
|
229
227
|
@c = Client.load(client_id, {:source_name => '*'})
|
230
|
-
@c.device_type.
|
231
|
-
@c.device_pin.
|
232
|
-
@c.id.length.
|
228
|
+
expect(@c.device_type).to eq('iPhone')
|
229
|
+
expect(@c.device_pin).to eq('abcd')
|
230
|
+
expect(@c.id.length).to eq(32)
|
233
231
|
end
|
234
232
|
|
235
233
|
it "should respond to clientreset" do
|
@@ -241,7 +239,7 @@ describe "Server" do
|
|
241
239
|
it "should respond to clientreset with old route and deprecation warning" do
|
242
240
|
set_doc_state(@c, :cd => @data)
|
243
241
|
get "/application/clientreset", 'client_id' => @c.id
|
244
|
-
last_response.headers["Warning"].index('deprecated').
|
242
|
+
expect(last_response.headers["Warning"].index('deprecated')).not_to be_nil
|
245
243
|
verify_doc_result(@c, :cd => {})
|
246
244
|
end
|
247
245
|
|
@@ -252,7 +250,7 @@ describe "Server" do
|
|
252
250
|
set_doc_state(@c, :cd => @data)
|
253
251
|
sources = [{'name' => 'SimpleAdapter'}]
|
254
252
|
do_post "/rc/#{Rhoconnect::API_VERSION}/clients/#{@c.id}/reset", 'sources' => sources
|
255
|
-
last_response.
|
253
|
+
expect(last_response).to be_ok
|
256
254
|
@c.source_name = 'SampleAdapter'
|
257
255
|
verify_doc_result(@c, :cd => @data)
|
258
256
|
@c.source_name = 'SimpleAdapter'
|
@@ -260,327 +258,327 @@ describe "Server" do
|
|
260
258
|
end
|
261
259
|
|
262
260
|
it "should switch client user if client user_id doesn't match session user" do
|
263
|
-
set_test_data('test_db_storage'
|
261
|
+
set_test_data('test_db_storage', @data)
|
264
262
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
265
|
-
JSON.parse(last_response.body).last['insert'].
|
266
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
267
|
-
data = {'1'
|
268
|
-
set_test_data('test_db_storage',data)
|
263
|
+
expect(JSON.parse(last_response.body).last['insert']).to eq(@data)
|
264
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => 'user2', "password" => 'testpass'
|
265
|
+
data = {'1' => @product1, '2' => @product2}
|
266
|
+
set_test_data('test_db_storage', data)
|
269
267
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
270
|
-
JSON.parse(last_response.body).last['insert'].
|
268
|
+
expect(JSON.parse(last_response.body).last['insert']).to eq(data)
|
271
269
|
end
|
272
270
|
|
273
271
|
it "should return error on routes if client doesn't exist" do
|
274
|
-
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}",{}, {Rhoconnect::CLIENT_ID_HEADER => "BrokenClient"}
|
275
|
-
last_response.body.
|
276
|
-
last_response.status.
|
272
|
+
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {}, {Rhoconnect::CLIENT_ID_HEADER => "BrokenClient"}
|
273
|
+
expect(last_response.body).to eq("Unknown client")
|
274
|
+
expect(last_response.status).to eq(500)
|
277
275
|
end
|
278
276
|
end
|
279
277
|
|
280
278
|
describe "source routes" do
|
281
279
|
before(:each) do
|
282
|
-
|
280
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'testpass'
|
283
281
|
end
|
284
282
|
|
285
283
|
it "should post records for create" do
|
286
284
|
@product1['_id'] = '1'
|
287
|
-
params = {'create'=>{'1'
|
285
|
+
params = {'create' => {'1' => @product1}}
|
288
286
|
do_post "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", params, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
289
|
-
last_response.
|
290
|
-
last_response.body.
|
291
|
-
verify_result("test_create_storage" => {'1'
|
287
|
+
expect(last_response).to be_ok
|
288
|
+
expect(last_response.body).to eq('')
|
289
|
+
verify_result("test_create_storage" => {'1' => @product1})
|
292
290
|
end
|
293
291
|
|
294
292
|
it "should post records for update" do
|
295
293
|
params = {'update' => @product1}
|
296
294
|
do_put "/app/#{Rhoconnect::API_VERSION}/#{@s.name}/1", params, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
297
|
-
last_response.
|
298
|
-
last_response.body.
|
299
|
-
verify_result("test_update_storage" => {'1'
|
295
|
+
expect(last_response).to be_ok
|
296
|
+
expect(last_response.body).to eq('')
|
297
|
+
verify_result("test_update_storage" => {'1' => @product1})
|
300
298
|
end
|
301
299
|
|
302
300
|
it "should post records for update using the old route and have the deprecation warning" do
|
303
|
-
params = {'update'=>{'1'
|
304
|
-
|
301
|
+
params = {'update' => {'1' => @product1}, :client_id => @c.id, :source_name => @s.name,
|
302
|
+
:version => Rhoconnect::SYNC_VERSION}
|
305
303
|
do_post "/application", params
|
306
|
-
last_response.
|
307
|
-
last_response.body.
|
308
|
-
last_response.headers["Warning"].index('deprecated').
|
309
|
-
verify_result("test_update_storage" => {'1'
|
304
|
+
expect(last_response).to be_ok
|
305
|
+
expect(last_response.body).to eq('')
|
306
|
+
expect(last_response.headers["Warning"].index('deprecated')).not_to be_nil
|
307
|
+
verify_result("test_update_storage" => {'1' => @product1})
|
310
308
|
end
|
311
309
|
|
312
310
|
it "should post records for delete" do
|
313
311
|
set_doc_state(@c, :cd => @data)
|
314
|
-
delete "/app/#{Rhoconnect::API_VERSION}/#{@s.name}/1", {}, {
|
315
|
-
last_response.
|
316
|
-
last_response.body.
|
317
|
-
verify_result("test_delete_storage" => {'1'
|
312
|
+
delete "/app/#{Rhoconnect::API_VERSION}/#{@s.name}/1", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
313
|
+
expect(last_response).to be_ok
|
314
|
+
expect(last_response.body).to eq('')
|
315
|
+
verify_result("test_delete_storage" => {'1' => @product1})
|
318
316
|
end
|
319
317
|
|
320
318
|
it "should post records for delete using the old route with deprecation warning" do
|
321
|
-
params = {'delete'=>{'1'
|
322
|
-
|
319
|
+
params = {'delete' => {'1' => @product1}, :client_id => @c.id, :source_name => @s.name,
|
320
|
+
:version => Rhoconnect::SYNC_VERSION}
|
323
321
|
do_post "/api/application/queue_updates", params
|
324
|
-
last_response.
|
325
|
-
last_response.headers["Warning"].index('deprecated').
|
326
|
-
last_response.body.
|
327
|
-
verify_result("test_delete_storage" => {'1'
|
322
|
+
expect(last_response).to be_ok
|
323
|
+
expect(last_response.headers["Warning"].index('deprecated')).not_to be_nil
|
324
|
+
expect(last_response.body).to eq('')
|
325
|
+
verify_result("test_delete_storage" => {'1' => @product1})
|
328
326
|
end
|
329
327
|
|
330
328
|
it "should handle client posting broken json" do
|
331
329
|
broken_json = "{\"foo\":\"bar\"\"}"
|
332
330
|
do_post "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", broken_json, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
333
|
-
last_response.status.
|
334
|
-
last_response.body.
|
331
|
+
expect(last_response.status).to eq(500)
|
332
|
+
expect(last_response.body).to eq("Server error while processing client data")
|
335
333
|
end
|
336
334
|
|
337
335
|
it "should not login if login is empty" do
|
338
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
339
|
-
last_response.status.
|
340
|
-
last_response.body.
|
336
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/login", ''
|
337
|
+
expect(last_response.status).to eq(401)
|
338
|
+
expect(last_response.body).to eq("Unable to authenticate ''")
|
341
339
|
end
|
342
340
|
|
343
|
-
|
344
|
-
expected = {'1'
|
345
|
-
set_test_data('test_db_storage',{'1'
|
341
|
+
xit "should resend page if page exists and no token provided" do
|
342
|
+
expected = {'1' => @product1}
|
343
|
+
set_test_data('test_db_storage', {'1' => @product1, '2' => @product2, '4' => @product4})
|
346
344
|
params = {'name' => 'iPhone'}
|
347
345
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {:query => params}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
348
|
-
last_response.
|
349
|
-
last_response.content_type.
|
346
|
+
expect(last_response).to be_ok
|
347
|
+
expect(last_response.content_type).to match /application\/json/
|
350
348
|
token = @c.get_value(:page_token)
|
351
|
-
last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER].
|
349
|
+
expect(last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER]).to eq(token)
|
352
350
|
last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER].should == 1.to_s
|
353
|
-
JSON.parse(last_response.body).
|
354
|
-
|
351
|
+
expect(JSON.parse(last_response.body)).to eq([{'version' => Rhoconnect::SYNC_VERSION}, {"token" => token},
|
352
|
+
{"count" => 1}, {"progress_count" => 0}, {"total_count" => 1}, {'insert' => expected}])
|
355
353
|
# this should re-send the page
|
356
354
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {:query => params}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
357
|
-
last_response.
|
358
|
-
last_response.content_type.
|
355
|
+
expect(last_response).to be_ok
|
356
|
+
expect(last_response.content_type).to match /application\/json/
|
359
357
|
token1 = @c.get_value(:page_token)
|
360
|
-
token1.
|
361
|
-
last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER].
|
358
|
+
expect(token1).to eq(token)
|
359
|
+
expect(last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER]).to eq(token)
|
362
360
|
last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER].should == 1.to_s
|
363
|
-
JSON.parse(last_response.body).should == [{'version'=>Rhoconnect::SYNC_VERSION}, {"token"=>token1},
|
364
|
-
|
361
|
+
JSON.parse(last_response.body).should == [{'version' => Rhoconnect::SYNC_VERSION}, {"token" => token1},
|
362
|
+
{"count" => 1}, {"progress_count" => 0}, {"total_count" => 1}, {'insert' => expected}]
|
365
363
|
# this should ack_token
|
366
364
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {:token => token, :query => params}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
367
|
-
last_response.
|
368
|
-
last_response.content_type.
|
365
|
+
expect(last_response).to be_ok
|
366
|
+
expect(last_response.content_type).to match /application\/json/
|
369
367
|
last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER].should == ""
|
370
368
|
last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER].should == 0.to_s
|
371
|
-
JSON.parse(last_response.body).should == [{'version'=>Rhoconnect::SYNC_VERSION}, {"token"=>""},
|
372
|
-
|
369
|
+
JSON.parse(last_response.body).should == [{'version' => Rhoconnect::SYNC_VERSION}, {"token" => ""},
|
370
|
+
{"count" => 0}, {"progress_count" => 0}, {"total_count" => 1}, {}]
|
373
371
|
@c.get_data(:page).should == {}
|
374
372
|
@c.get_value(:page_token).should be_nil
|
375
373
|
end
|
376
374
|
|
377
375
|
it "should get inserts json" do
|
378
|
-
data = {'1'
|
379
|
-
set_test_data('test_db_storage',data)
|
376
|
+
data = {'1' => @product1, '2' => @product2}
|
377
|
+
set_test_data('test_db_storage', data)
|
380
378
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
381
|
-
last_response.
|
382
|
-
last_response.content_type.
|
379
|
+
expect(last_response).to be_ok
|
380
|
+
expect(last_response.content_type).to match /application\/json/
|
383
381
|
token = @c.get_value(:page_token)
|
384
|
-
JSON.parse(last_response.body).
|
385
|
-
|
382
|
+
expect(JSON.parse(last_response.body)).to eq([{'version' => Rhoconnect::SYNC_VERSION}, {"token" => token},
|
383
|
+
{"count" => 2}, {"progress_count" => 0}, {"total_count" => 2}, {'insert' => data}])
|
386
384
|
end
|
387
385
|
|
388
386
|
it "should get inserts json with the old route and show deprecation warning" do
|
389
|
-
data = {'1'
|
390
|
-
set_test_data('test_db_storage',data)
|
391
|
-
get "/application"
|
392
|
-
last_response.
|
393
|
-
last_response.headers["Warning"].index('deprecated').
|
394
|
-
last_response.content_type.
|
387
|
+
data = {'1' => @product1, '2' => @product2}
|
388
|
+
set_test_data('test_db_storage', data)
|
389
|
+
get "/application", :client_id => @c.id, :source_name => @s.name, :version => Rhoconnect::SYNC_VERSION
|
390
|
+
expect(last_response).to be_ok
|
391
|
+
expect(last_response.headers["Warning"].index('deprecated')).not_to be_nil
|
392
|
+
expect(last_response.content_type).to match /application\/json/
|
395
393
|
token = @c.get_value(:page_token)
|
396
|
-
JSON.parse(last_response.body).
|
397
|
-
|
394
|
+
expect(JSON.parse(last_response.body)).to eq([{'version' => Rhoconnect::SYNC_VERSION}, {"token" => token},
|
395
|
+
{"count" => 2}, {"progress_count" => 0}, {"total_count" => 2}, {'insert' => data}])
|
398
396
|
end
|
399
397
|
|
400
398
|
it "should get inserts json and confirm token" do
|
401
|
-
data = {'1'
|
402
|
-
set_test_data('test_db_storage',data)
|
399
|
+
data = {'1' => @product1, '2' => @product2}
|
400
|
+
set_test_data('test_db_storage', data)
|
403
401
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
404
|
-
last_response.
|
402
|
+
expect(last_response).to be_ok
|
405
403
|
token = @c.get_value(:page_token)
|
406
|
-
JSON.parse(last_response.body).
|
407
|
-
|
404
|
+
expect(JSON.parse(last_response.body)).to eq([{'version' => Rhoconnect::SYNC_VERSION}, {"token" => token},
|
405
|
+
{"count" => 2}, {"progress_count" => 0}, {"total_count" => 2}, {'insert' => data}])
|
408
406
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {:token => token}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
409
|
-
last_response.
|
410
|
-
JSON.parse(last_response.body).
|
411
|
-
|
407
|
+
expect(last_response).to be_ok
|
408
|
+
expect(JSON.parse(last_response.body)).to eq([{'version' => Rhoconnect::SYNC_VERSION}, {"token" => ''},
|
409
|
+
{"count" => 0}, {"progress_count" => 0}, {"total_count" => 2}, {}])
|
412
410
|
end
|
413
411
|
|
414
412
|
# check custom partitions
|
415
413
|
it "should return data for user with custom partition name" do
|
416
414
|
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => 'cus_user1', "password" => 'testpass'
|
417
415
|
@c_fields = {
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
416
|
+
:device_type => 'Apple',
|
417
|
+
:device_pin => 'abcd',
|
418
|
+
:device_port => '3333',
|
419
|
+
:user_id => 'cus_user1',
|
420
|
+
:app_id => @a.id
|
423
421
|
}
|
424
|
-
@c = Client.create(@c_fields,{:source_name => @s_fields[:name]})
|
422
|
+
@c = Client.create(@c_fields, {:source_name => @s_fields[:name]})
|
425
423
|
@s = Source.load('SampleAdapter', {:user_id => 'cus_user1', :app_id => APP_NAME})
|
426
424
|
|
427
|
-
data = {'1'
|
428
|
-
set_test_data('test_db_storage',data)
|
425
|
+
data = {'1' => @product1, '2' => @product2}
|
426
|
+
set_test_data('test_db_storage', data)
|
429
427
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
430
|
-
last_response.
|
428
|
+
expect(last_response).to be_ok
|
431
429
|
token = @c.get_value(:page_token)
|
432
|
-
JSON.parse(last_response.body).
|
433
|
-
|
430
|
+
expect(JSON.parse(last_response.body)).to eq([{'version' => Rhoconnect::SYNC_VERSION}, {"token" => token},
|
431
|
+
{"count" => 2}, {"progress_count" => 0}, {"total_count" => 2}, {'insert' => data}])
|
434
432
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {:token => token}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
435
|
-
last_response.
|
436
|
-
JSON.parse(last_response.body).
|
437
|
-
|
438
|
-
@s.docname(:md).
|
433
|
+
expect(last_response).to be_ok
|
434
|
+
expect(JSON.parse(last_response.body)).to eq([{'version' => Rhoconnect::SYNC_VERSION}, {"token" => ''},
|
435
|
+
{"count" => 0}, {"progress_count" => 0}, {"total_count" => 2}, {}])
|
436
|
+
expect(@s.docname(:md)).to eq("source:#{@s.app.id}:custom_partition:SampleAdapter:md")
|
439
437
|
verify_doc_result(@s, :md => data)
|
440
438
|
end
|
441
439
|
|
442
440
|
it "should create source for dynamic adapter if source_name is unknown" do
|
443
441
|
get "/app/#{Rhoconnect::API_VERSION}/Broken", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
444
|
-
last_response.status.
|
442
|
+
expect(last_response.status).to eq(200)
|
445
443
|
end
|
446
444
|
|
447
445
|
it "should create source for dynamic adapter if source_name is unknown using the old route" do
|
448
446
|
get "/api/application/query", {:source_name => @s_fields[:name], :client_id => @c.id}
|
449
|
-
last_response.status.
|
447
|
+
expect(last_response.status).to eq(200)
|
450
448
|
end
|
451
449
|
|
452
450
|
it "should get deletes json" do
|
453
|
-
@s = Source.load(@s_fields[:name]
|
454
|
-
data = {'1'
|
455
|
-
set_test_data('test_db_storage',data)
|
451
|
+
@s = Source.load(@s_fields[:name], @s_params)
|
452
|
+
data = {'1' => @product1, '2' => @product2}
|
453
|
+
set_test_data('test_db_storage', data)
|
456
454
|
|
457
455
|
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
458
|
-
last_response.
|
456
|
+
expect(last_response).to be_ok
|
459
457
|
token = @c.get_value(:page_token)
|
460
|
-
last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER].
|
461
|
-
last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER].
|
462
|
-
JSON.parse(last_response.body).
|
463
|
-
|
458
|
+
expect(last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER]).to eq(token)
|
459
|
+
expect(last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER]).to eq(2.to_s)
|
460
|
+
expect(JSON.parse(last_response.body)).to eq([{'version' => Rhoconnect::SYNC_VERSION}, {"token" => token},
|
461
|
+
{"count" => 2}, {"progress_count" => 0}, {"total_count" => 2}, {'insert' => data}])
|
464
462
|
|
465
463
|
Store.flush_data('test_db_storage')
|
466
464
|
@s.read_state.refresh_time = Time.now.to_i
|
467
465
|
|
468
|
-
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}",{:token => token}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
469
|
-
last_response.
|
466
|
+
get "/app/#{Rhoconnect::API_VERSION}/#{@s.name}", {:token => token}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
467
|
+
expect(last_response).to be_ok
|
470
468
|
token = @c.get_value(:page_token)
|
471
|
-
last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER].
|
472
|
-
last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER].
|
473
|
-
JSON.parse(last_response.body).
|
474
|
-
|
469
|
+
expect(last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER]).to eq(token)
|
470
|
+
expect(last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER]).to eq(2.to_s)
|
471
|
+
expect(JSON.parse(last_response.body)).to eq([{'version' => Rhoconnect::SYNC_VERSION}, {"token" => token},
|
472
|
+
{"count" => 2}, {"progress_count" => 0}, {"total_count" => 0}, {'delete' => data}])
|
475
473
|
end
|
476
474
|
|
477
475
|
it "should get search results using the old route with deprecation warning" do
|
478
|
-
sources = [{:name=>'SampleAdapter'}]
|
479
|
-
Store.put_data('test_db_storage'
|
480
|
-
params = {:client_id => @c.id
|
481
|
-
|
482
|
-
get "/api/application/search",params
|
483
|
-
last_response.headers['Warning'].index('deprecated').
|
484
|
-
last_response.content_type.
|
476
|
+
sources = [{:name => 'SampleAdapter'}]
|
477
|
+
Store.put_data('test_db_storage', @data)
|
478
|
+
params = {:client_id => @c.id, :sources => sources, :search => {'name' => 'iPhone'},
|
479
|
+
:version => Rhoconnect::SYNC_VERSION}
|
480
|
+
get "/api/application/search", params
|
481
|
+
expect(last_response.headers['Warning'].index('deprecated')).not_to be_nil
|
482
|
+
expect(last_response.content_type).to match /application\/json/
|
485
483
|
token = @c.get_value(:search_token)
|
486
|
-
last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER].
|
487
|
-
last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER].
|
488
|
-
JSON.parse(last_response.body).
|
489
|
-
|
484
|
+
expect(last_response.headers[Rhoconnect::PAGE_TOKEN_HEADER]).to eq(token)
|
485
|
+
expect(last_response.headers[Rhoconnect::PAGE_OBJECT_COUNT_HEADER]).to eq(1.to_s)
|
486
|
+
expect(JSON.parse(last_response.body)).to eq([[{'version' => Rhoconnect::SYNC_VERSION}, {'token' => token},
|
487
|
+
{'source' => sources[0][:name]}, {'count' => 1}, {'insert' => {'1' => @product1}}]])
|
490
488
|
end
|
491
489
|
|
492
490
|
it "should get search results" do
|
493
|
-
sources = [{:name=>'SampleAdapter'}]
|
494
|
-
Store.put_data('test_db_storage'
|
495
|
-
params = {:sources => sources
|
496
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/search",params, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
497
|
-
last_response.content_type.
|
491
|
+
sources = [{:name => 'SampleAdapter'}]
|
492
|
+
Store.put_data('test_db_storage', @data)
|
493
|
+
params = {:sources => sources, :search => {'name' => 'iPhone'}}
|
494
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/search", params, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
495
|
+
expect(last_response.content_type).to match /application\/json/
|
498
496
|
token = @c.get_value(:search_token)
|
499
|
-
JSON.parse(last_response.body).
|
500
|
-
|
497
|
+
expect(JSON.parse(last_response.body)).to eq([[{'version' => Rhoconnect::SYNC_VERSION}, {'token' => token},
|
498
|
+
{'source' => sources[0][:name]}, {'count' => 1}, {'insert' => {'1' => @product1}}]])
|
501
499
|
end
|
502
500
|
|
503
501
|
it "should get search results with error" do
|
504
|
-
sources = [{:name=>'SampleAdapter'}]
|
502
|
+
sources = [{:name => 'SampleAdapter'}]
|
505
503
|
msg = "Error during search"
|
506
|
-
error = set_test_data('test_db_storage'
|
507
|
-
params = {:sources => sources
|
504
|
+
error = set_test_data('test_db_storage', @data, msg, 'search error')
|
505
|
+
params = {:sources => sources, :search => {'name' => 'iPhone'}}
|
508
506
|
do_post "/rc/#{Rhoconnect::API_VERSION}/app/search", params, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
509
|
-
JSON.parse(last_response.body).
|
510
|
-
|
507
|
+
expect(JSON.parse(last_response.body)).to eq([[{'version' => Rhoconnect::SYNC_VERSION}, {'source' => sources[0][:name]},
|
508
|
+
{'search-error' => {'search-error' => {'message' => msg}}}]])
|
511
509
|
verify_doc_result(@c, :search => {})
|
512
510
|
end
|
513
511
|
|
514
512
|
it "should get multiple source search results" do
|
515
|
-
Store.put_data('test_db_storage'
|
516
|
-
sources = [{:name=>'SimpleAdapter'},{:name=>'SampleAdapter'}]
|
517
|
-
params = {:sources => sources
|
513
|
+
Store.put_data('test_db_storage', @data)
|
514
|
+
sources = [{:name => 'SimpleAdapter'}, {:name => 'SampleAdapter'}]
|
515
|
+
params = {:sources => sources, :search => {'search' => 'bar'}}
|
518
516
|
do_post "/rc/#{Rhoconnect::API_VERSION}/app/search", params, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
519
517
|
@c.source_name = 'SimpleAdapter'
|
520
518
|
token1 = @c.get_value(:search_token)
|
521
519
|
@c.source_name = 'SampleAdapter'
|
522
520
|
token = @c.get_value(:search_token)
|
523
|
-
JSON.parse(last_response.body).
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
verify_doc_result(@c, {:search => {'1'
|
521
|
+
expect(JSON.parse(last_response.body)).to eq([
|
522
|
+
[{'version' => Rhoconnect::SYNC_VERSION}, {'token' => token1}, {"source" => "SimpleAdapter"},
|
523
|
+
{"count" => 1}, {"insert" => {'obj' => {'foo' => 'bar'}}}],
|
524
|
+
[{'version' => Rhoconnect::SYNC_VERSION}, {'token' => token}, {"source" => "SampleAdapter"},
|
525
|
+
{"count" => 1}, {"insert" => {'1' => @product1}}]])
|
526
|
+
verify_doc_result(@c, {:search => {'1' => @product1},
|
529
527
|
:search_errors => {}})
|
530
528
|
end
|
531
529
|
|
532
530
|
it "should handle search for pass through" do
|
533
|
-
sources = [{'name'=>'SampleAdapter'}]
|
531
|
+
sources = [{'name' => 'SampleAdapter'}]
|
534
532
|
set_state('test_db_storage' => @data)
|
535
533
|
@s.pass_through = 'true'
|
536
534
|
params = {:sources => sources, :search => {'name' => 'iPhone'}}
|
537
535
|
do_post "/rc/#{Rhoconnect::API_VERSION}/app/search", params, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
538
536
|
token = @c.get_value(:search_token)
|
539
|
-
JSON.parse(last_response.body).
|
540
|
-
|
537
|
+
expect(JSON.parse(last_response.body)).to eq([[{'version' => Rhoconnect::SYNC_VERSION}, {'token' => token},
|
538
|
+
{'source' => sources[0]['name']}, {'count' => 1}, {'insert' => {'1' => @product1}}]])
|
541
539
|
verify_doc_result(@c, {:search => {},
|
542
540
|
:search_errors => {}})
|
543
541
|
end
|
544
542
|
|
545
543
|
it "should handle multiple source search with one source returning nothing" do
|
546
|
-
set_test_data('test_db_storage'
|
547
|
-
sources = [{'name'=>'SimpleAdapter'},{'name'=>'SampleAdapter'}]
|
548
|
-
params = {:sources => sources
|
544
|
+
set_test_data('test_db_storage', @data)
|
545
|
+
sources = [{'name' => 'SimpleAdapter'}, {'name' => 'SampleAdapter'}]
|
546
|
+
params = {:sources => sources, :search => {'name' => 'iPhone'}}
|
549
547
|
do_post "/rc/#{Rhoconnect::API_VERSION}/app/search", params, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
550
548
|
@c.source_name = 'SimpleAdapter'
|
551
549
|
token1 = @c.get_value(:search_token)
|
552
|
-
token1.
|
550
|
+
expect(token1).to be_nil
|
553
551
|
@c.source_name = 'SampleAdapter'
|
554
552
|
token = @c.get_value(:search_token)
|
555
|
-
JSON.parse(last_response.body).
|
556
|
-
|
553
|
+
expect(JSON.parse(last_response.body)).to eq([[], [{'version' => Rhoconnect::SYNC_VERSION}, {'token' => token},
|
554
|
+
{"source" => "SampleAdapter"}, {"count" => 1}, {"insert" => {'1' => @product1}}]])
|
557
555
|
end
|
558
556
|
|
559
557
|
it "should handle search and ack of search results" do
|
560
|
-
set_test_data('test_db_storage'
|
561
|
-
sources = [{'name'=>'SimpleAdapter'},{'name'=>'SampleAdapter'}]
|
562
|
-
params = {:sources => sources
|
558
|
+
set_test_data('test_db_storage', @data)
|
559
|
+
sources = [{'name' => 'SimpleAdapter'}, {'name' => 'SampleAdapter'}]
|
560
|
+
params = {:sources => sources, :search => {'search' => 'bar'}}
|
563
561
|
do_post "/rc/#{Rhoconnect::API_VERSION}/app/search", params, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
564
562
|
@c.source_name = 'SimpleAdapter'
|
565
563
|
token = @c.get_value(:search_token)
|
566
|
-
token.
|
564
|
+
expect(token).not_to be_nil
|
567
565
|
sources[0]['token'] = token
|
568
|
-
@c.get_data(:search).
|
566
|
+
expect(@c.get_data(:search)).to eq({'obj' => {'foo' => 'bar'}})
|
569
567
|
@c.source_name = 'SampleAdapter'
|
570
568
|
token1 = @c.get_value(:search_token)
|
571
|
-
token1.
|
569
|
+
expect(token1).not_to be_nil
|
572
570
|
sources[1]['token'] = token1
|
573
|
-
@c.get_data(:search).
|
571
|
+
expect(@c.get_data(:search)).to eq('1' => @product1)
|
574
572
|
# do ack on multiple sources
|
575
573
|
do_post "/rc/#{Rhoconnect::API_VERSION}/app/search", params, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
576
574
|
@c.source_name = 'SimpleAdapter'
|
577
575
|
token = @c.get_value(:search_token)
|
578
|
-
token.
|
579
|
-
@c.get_data(:search).
|
576
|
+
expect(token).to be_nil
|
577
|
+
expect(@c.get_data(:search)).to eq({})
|
580
578
|
@c.source_name = 'SampleAdapter'
|
581
579
|
token1 = @c.get_value(:search_token)
|
582
|
-
token1.
|
583
|
-
@c.get_data(:search).
|
580
|
+
expect(token1).to be_nil
|
581
|
+
expect(@c.get_data(:search)).to eq({})
|
584
582
|
end
|
585
583
|
end
|
586
584
|
|
@@ -596,117 +594,117 @@ describe "Server" do
|
|
596
594
|
it "should make initial bulk data request (which creates Resque job) and receive wait (and no deprecation warning)" do
|
597
595
|
set_state('test_db_storage' => @data)
|
598
596
|
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
599
|
-
last_response.
|
600
|
-
last_response.body.
|
597
|
+
expect(last_response).to be_ok
|
598
|
+
expect(last_response.body).to eq({:result => :wait}.to_json)
|
601
599
|
warning_header = last_response.headers['Warning']
|
602
|
-
warning_header.
|
603
|
-
Resque.peek(:bulk_data).
|
604
|
-
|
605
|
-
|
600
|
+
expect(warning_header).to be_nil or expect(warning_header.index('deprecated')).to be_nil
|
601
|
+
expect(Resque.peek(:bulk_data)).to eq({"args" =>
|
602
|
+
[{"data_name" => File.join(@a_fields[:name], @u_fields[:login], @u_fields[:login])}],
|
603
|
+
"class" => "Rhoconnect::BulkDataJob"})
|
606
604
|
end
|
607
605
|
|
608
606
|
it "should make old-way initial bulk data request and receive wait along with deprecation warning" do
|
609
607
|
set_state('test_db_storage' => @data)
|
610
608
|
get "/application/bulk_data", :partition => :user, :client_id => @c.id
|
611
|
-
last_response.
|
612
|
-
last_response.body.
|
613
|
-
last_response.headers['Warning'].index('deprecated').
|
609
|
+
expect(last_response).to be_ok
|
610
|
+
expect(last_response.body).to eq({:result => :wait}.to_json)
|
611
|
+
expect(last_response.headers['Warning'].index('deprecated')).not_to be_nil
|
614
612
|
end
|
615
613
|
|
616
614
|
it "should make old-way initial bulk data request and receive wait along with deprecation warning (Sources sent as String)" do
|
617
615
|
set_state('test_db_storage' => @data)
|
618
616
|
get "/application/bulk_data?sources=FixedSchemaAdapter,SampleAdapter", :partition => :user, :client_id => @c.id
|
619
|
-
last_response.
|
620
|
-
last_response.body.
|
621
|
-
last_response.headers['Warning'].index('deprecated').
|
617
|
+
expect(last_response).to be_ok
|
618
|
+
expect(last_response.body).to eq({:result => :wait}.to_json)
|
619
|
+
expect(last_response.headers['Warning'].index('deprecated')).not_to be_nil
|
622
620
|
end
|
623
621
|
|
624
622
|
it "should receive url when bulk data is available" do
|
625
623
|
set_state('test_db_storage' => @data)
|
626
624
|
@a.sources.delete('JsSample')
|
627
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
628
|
-
do_bulk_data_job("data_name" => bulk_data_docname(@a.id
|
629
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
630
|
-
last_response.
|
631
|
-
data = BulkData.load(bulk_data_docname(@a.id
|
632
|
-
last_response.body.
|
633
|
-
|
634
|
-
validate_db(data,{@s.name => @data, 'FixedSchemaAdapter' => @data})
|
625
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
626
|
+
do_bulk_data_job("data_name" => bulk_data_docname(@a.id, @u.id))
|
627
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
628
|
+
expect(last_response).to be_ok
|
629
|
+
data = BulkData.load(bulk_data_docname(@a.id, @u.id))
|
630
|
+
expect(last_response.body).to eq({:result => :url,
|
631
|
+
:url => data.url}.to_json)
|
632
|
+
validate_db(data, {@s.name => @data, 'FixedSchemaAdapter' => @data})
|
635
633
|
end
|
636
634
|
|
637
635
|
it "should download bulk data file" do
|
638
636
|
set_state('test_db_storage' => @data)
|
639
637
|
@a.sources.delete('JsSample')
|
640
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
641
|
-
do_bulk_data_job("data_name" => bulk_data_docname(@a.id
|
642
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
643
|
-
JSON.parse(last_response.body).
|
644
|
-
'url' => BulkData.load(bulk_data_docname(@a.id
|
638
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
639
|
+
do_bulk_data_job("data_name" => bulk_data_docname(@a.id, @u.id))
|
640
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
641
|
+
expect(JSON.parse(last_response.body)).to eq({'result' => 'url',
|
642
|
+
'url' => BulkData.load(bulk_data_docname(@a.id, @u.id)).url})
|
645
643
|
get JSON.parse(last_response.body)["url"]
|
646
|
-
last_response.
|
647
|
-
File.open('test.data','wb') {|f| f.puts last_response.body}
|
648
|
-
validate_db_file('test.data',[@s.name,'FixedSchemaAdapter'],{@s.name => @data, 'FixedSchemaAdapter' => @data})
|
644
|
+
expect(last_response).to be_ok
|
645
|
+
File.open('test.data', 'wb') {|f| f.puts last_response.body}
|
646
|
+
validate_db_file('test.data', [@s.name, 'FixedSchemaAdapter'], {@s.name => @data, 'FixedSchemaAdapter' => @data})
|
649
647
|
File.delete('test.data')
|
650
648
|
verify_doc_result(@c, :cd => @data)
|
651
649
|
verify_doc_result(@s, {:md => @data,
|
652
|
-
|
650
|
+
:md_copy => @data})
|
653
651
|
end
|
654
652
|
|
655
653
|
it "should receive nop when no sources are available for partition" do
|
656
654
|
set_state('test_db_storage' => @data)
|
657
|
-
Source.load('SimpleAdapter'
|
655
|
+
Source.load('SimpleAdapter', @s_params).partition = :user
|
658
656
|
@a.sources.delete('OtherAdapter')
|
659
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
660
|
-
last_response.
|
661
|
-
last_response.body.
|
657
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :app}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
658
|
+
expect(last_response).to be_ok
|
659
|
+
expect(last_response.body).to eq({:result => :nop}.to_json)
|
662
660
|
end
|
663
661
|
|
664
662
|
it "should create bulk data job app partition with partition sources" do
|
665
663
|
@s.partition = :app
|
666
664
|
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :app}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
667
|
-
last_response.
|
668
|
-
last_response.body.
|
665
|
+
expect(last_response).to be_ok
|
666
|
+
expect(last_response.body).to eq({:result => :wait}.to_json)
|
669
667
|
warning_header = last_response.headers['Warning']
|
670
|
-
warning_header.
|
671
|
-
Resque.peek(:bulk_data).
|
672
|
-
|
673
|
-
|
668
|
+
expect(warning_header).to be_nil or expect(warning_header.index('deprecated')).to be_nil
|
669
|
+
expect(Resque.peek(:bulk_data)).to eq({"args" =>
|
670
|
+
[{"data_name" => File.join(@a_fields[:name], @a_fields[:name])}],
|
671
|
+
"class" => "Rhoconnect::BulkDataJob"})
|
674
672
|
end
|
675
673
|
|
676
674
|
it "should return empty bulk data url if there are errors in query" do
|
677
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
678
|
-
do_bulk_data_job("data_name" => bulk_data_docname(@a.id
|
675
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
676
|
+
do_bulk_data_job("data_name" => bulk_data_docname(@a.id, @u.id))
|
679
677
|
operation = 'query'
|
680
678
|
@s.lock(:errors) do
|
681
|
-
@s.put_data(:errors,{"#{operation}-error"=>{'message'=>"Some exception message"}}, true)
|
679
|
+
@s.put_data(:errors, {"#{operation}-error" => {'message' => "Some exception message"}}, true)
|
682
680
|
end
|
683
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
684
|
-
JSON.parse(last_response.body).
|
681
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
682
|
+
expect(JSON.parse(last_response.body)).to eq('result' => 'url', 'url' => '')
|
685
683
|
end
|
686
684
|
|
687
685
|
it "should return bulk data url for completed bulk data app partition" do
|
688
686
|
set_state('test_db_storage' => @data)
|
689
687
|
@s.partition = :app
|
690
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
691
|
-
do_bulk_data_job("data_name" => bulk_data_docname(@a.id,"*"))
|
692
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
693
|
-
JSON.parse(last_response.body).
|
694
|
-
|
688
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :app}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
689
|
+
do_bulk_data_job("data_name" => bulk_data_docname(@a.id, "*"))
|
690
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :app}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
691
|
+
expect(JSON.parse(last_response.body)).to eq({'result' => 'url',
|
692
|
+
'url' => BulkData.load(bulk_data_docname(@a.id, "*")).url})
|
695
693
|
@c.source_name = @s.name
|
696
694
|
verify_doc_result(@c, :cd => @data)
|
697
695
|
verify_doc_result(@s, {:md => @data,
|
698
|
-
|
696
|
+
:md_copy => @data})
|
699
697
|
end
|
700
698
|
|
701
699
|
it "should return bulk data url for completed bulk data with bulk_sync_only source" do
|
702
700
|
set_state('test_db_storage' => @data)
|
703
701
|
@a.sources.delete('JsSample')
|
704
702
|
@s.sync_type = :bulk_sync_only
|
705
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
706
|
-
do_bulk_data_job("data_name" => bulk_data_docname(@a.id
|
707
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
708
|
-
JSON.parse(last_response.body).
|
709
|
-
|
703
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
704
|
+
do_bulk_data_job("data_name" => bulk_data_docname(@a.id, @u.id))
|
705
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
706
|
+
expect(JSON.parse(last_response.body)).to eq({'result' => 'url',
|
707
|
+
'url' => BulkData.load(bulk_data_docname(@a.id, @u.id)).url})
|
710
708
|
@c.source_name = @s.name
|
711
709
|
verify_doc_result(@c, :cd => {})
|
712
710
|
verify_doc_result(@s, {:md => @data,
|
@@ -716,42 +714,42 @@ describe "Server" do
|
|
716
714
|
it "should create bulk data job if no file exists" do
|
717
715
|
set_state('test_db_storage' => @data)
|
718
716
|
@a.sources.delete('JsSample')
|
719
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
720
|
-
do_bulk_data_job("data_name" => bulk_data_docname(@a.id
|
721
|
-
data = BulkData.load(bulk_data_docname(@a.id
|
722
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
723
|
-
JSON.parse(last_response.body).
|
717
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
718
|
+
do_bulk_data_job("data_name" => bulk_data_docname(@a.id, @u.id))
|
719
|
+
data = BulkData.load(bulk_data_docname(@a.id, @u.id))
|
720
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
721
|
+
expect(JSON.parse(last_response.body)).to eq({'result' => 'url', 'url' => data.url})
|
724
722
|
File.delete(data.dbfile)
|
725
|
-
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data",
|
726
|
-
JSON.parse(last_response.body).
|
727
|
-
Resque.peek(:bulk_data).
|
728
|
-
|
723
|
+
post "/rc/#{Rhoconnect::API_VERSION}/app/bulk_data", {:partition => :user}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
724
|
+
expect(JSON.parse(last_response.body)).to eq({'result' => 'wait'})
|
725
|
+
expect(Resque.peek(:bulk_data)).to eq({"args" =>
|
726
|
+
[{"data_name" => bulk_data_docname(@a.id, @u.id)}], "class" => "Rhoconnect::BulkDataJob"})
|
729
727
|
end
|
730
728
|
end
|
731
729
|
|
732
730
|
describe "blob sync" do
|
733
731
|
before(:each) do
|
734
|
-
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login",
|
732
|
+
do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'testpass'
|
735
733
|
end
|
736
734
|
it "should upload blob in multipart post" do
|
737
|
-
file1,file2 = 'upload1.txt','upload2.txt'
|
735
|
+
file1, file2 = 'upload1.txt', 'upload2.txt'
|
738
736
|
@product1['txtfile-rhoblob'] = file1
|
739
737
|
@product1['_id'] = 'tempobj1'
|
740
738
|
@product2['txtfile-rhoblob'] = file2
|
741
739
|
@product2['_id'] = 'tempobj2'
|
742
|
-
cud = {'create'=>{'1'
|
743
|
-
|
740
|
+
cud = {'create' => {'1' => @product1, '2' => @product2},
|
741
|
+
:blob_fields => ['txtfile-rhoblob']}.to_json
|
744
742
|
post "/app/#{Rhoconnect::API_VERSION}/#{@s.name}",
|
745
|
-
|
746
|
-
|
747
|
-
|
748
|
-
|
749
|
-
last_response.
|
743
|
+
{:cud => cud, 'txtfile-rhoblob-1' =>
|
744
|
+
Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), '..', 'testdata', file1), "application/octet-stream"),
|
745
|
+
'txtfile-rhoblob-2' =>
|
746
|
+
Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__), '..', 'testdata', file2), "application/octet-stream")}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
|
747
|
+
expect(last_response).to be_ok
|
750
748
|
data = Store.get_data('test_create_storage')
|
751
|
-
data.size.
|
752
|
-
data.each do |id,obj|
|
753
|
-
File.exists?(obj['txtfile-rhoblob']).
|
749
|
+
expect(data.size).to eq(2)
|
750
|
+
data.each do |id, obj|
|
751
|
+
expect(File.exists?(obj['txtfile-rhoblob'])).to be true
|
754
752
|
end
|
755
753
|
end
|
756
754
|
end
|
757
|
-
end
|
755
|
+
end
|