rhoconnect 4.0.0 → 4.0.1

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 (56) hide show
  1. data/CHANGELOG.md +8 -0
  2. data/Gemfile.lock +16 -18
  3. data/Rakefile +4 -4
  4. data/bench/benchapp/Rakefile +10 -16
  5. data/bench/blobapp/Rakefile +9 -18
  6. data/bench/distr_bench/distr_bench_main +1 -1
  7. data/bench/distr_bench/run_distr_client.sh +2 -1
  8. data/bench/lib/bench.rb +1 -1
  9. data/bench/lib/bench/cli.rb +2 -0
  10. data/bench/lib/bench/distr_runner.rb +5 -5
  11. data/bench/lib/bench/test_data.rb +2 -2
  12. data/bench/scripts/test_query_script.rb +7 -6
  13. data/bin/rhoconnect +2 -0
  14. data/bin/rhoconnect-benchmark +13 -1
  15. data/commands/redis/redis_download.rb +1 -1
  16. data/commands/rhoconnect/routes.rb +12 -0
  17. data/doc/authentication.txt +1 -1
  18. data/doc/command-line.txt +1 -1
  19. data/doc/deploying.txt +2 -2
  20. data/doc/migration.txt +21 -12
  21. data/doc/push-client-setup-android.txt +1 -1
  22. data/doc/push-client-setup-rps.txt +3 -1
  23. data/doc/supported-platforms.txt +14 -7
  24. data/examples/simple/Rakefile +0 -1
  25. data/generators/rhoconnect.rb +15 -3
  26. data/generators/templates/application/Rakefile +1 -2
  27. data/js-adapters/ballroom.js +36 -9
  28. data/js-adapters/node.rb +8 -2
  29. data/js-adapters/node_channel.rb +10 -6
  30. data/js-adapters/rhoconnect_helpers.js +4 -0
  31. data/js-adapters/router.js +5 -3
  32. data/js-adapters/server.js +1 -1
  33. data/lib/rhoconnect.rb +9 -5
  34. data/lib/rhoconnect/api_token.rb +1 -2
  35. data/lib/rhoconnect/client.rb +1 -1
  36. data/lib/rhoconnect/controller/js_base.rb +7 -2
  37. data/lib/rhoconnect/model/base.rb +1 -1
  38. data/lib/rhoconnect/predefined_adapters/controllers/js/rho_internal_js_bench_adapter_controller.js +12 -0
  39. data/lib/rhoconnect/predefined_adapters/models/js/rho_internal_js_bench_adapter.js +107 -0
  40. data/lib/rhoconnect/source.rb +5 -0
  41. data/lib/rhoconnect/store.rb +3 -0
  42. data/lib/rhoconnect/version.rb +1 -1
  43. data/lib/rhoconnect/web-console/server.rb +1 -2
  44. data/rhoconnect.gemspec +0 -1
  45. data/spec/apps/jstestapp/Rakefile +1 -0
  46. data/spec/apps/jstestapp/config.ru +16 -0
  47. data/spec/apps/jstestapp/controllers/js/application_controller.js +18 -0
  48. data/spec/apps/jstestapp/settings/license.key +1 -0
  49. data/spec/apps/jstestapp/settings/settings.yml +13 -0
  50. data/spec/controllers/js_base_spec.rb +129 -97
  51. data/spec/predefined_adapters/rho_internal_bench_adapter_controller_js_spec.rb +111 -0
  52. data/spec/predefined_adapters/rho_internal_js_bench_adapter_js_spec.rb +44 -0
  53. data/spec/spec_helper.rb +4 -0
  54. data/tasks/redis.rake +9 -127
  55. metadata +19 -20
  56. data/lib/rhoconnect/tasks.rb +0 -315
@@ -1,5 +1,5 @@
1
1
  var ballroom = require('./ballroom');
2
- var channel = process.argv[2] + "RedisSUB";
2
+ var channel = process.argv[2] + "-RedisSUB";
3
3
 
4
4
  ballroom.listen(channel);
5
5
  ballroom.register();
@@ -2,6 +2,7 @@ require 'redis'
2
2
  require 'cgi'
3
3
  require 'json'
4
4
  require 'base64'
5
+ require 'securerandom'
5
6
  require 'zip/zip'
6
7
  require 'yaml'
7
8
  require 'rhoconnect/license'
@@ -55,7 +56,7 @@ module Rhoconnect
55
56
  :log_disabled, :license, :bulk_sync_poll_interval, :stats, :appserver, :api_token,
56
57
  :raise_on_expired_lock, :lock_duration, :cookie_expire, :predefined_sources,
57
58
  :connection_pool_size, :connection_pool_timeout, :redis_timeout, :store_key_ttl,
58
- :disable_resque_console, :disable_rc_console, :use_node, :restart_node_on_error
59
+ :disable_resque_console, :disable_rc_console, :use_node, :restart_node_on_error, :redis_url
59
60
  end
60
61
 
61
62
  # this mixin adds the controller into the Application's URL Map
@@ -69,10 +70,13 @@ module Rhoconnect
69
70
  # Rhoconnect API version
70
71
  def add_to_url_map(subclass)
71
72
  @controllers_map ||= Set.new
72
- #puts " adding to URL map #{subclass.name}"
73
73
  @controllers_map << subclass
74
74
  end
75
75
 
76
+ def remove_from_url_map(subclass)
77
+ @controllers_map.delete(subclass) if @controllers_map
78
+ end
79
+
76
80
  def url_map
77
81
  @controllers_map ||= Set.new
78
82
  app_url_map = {}
@@ -288,9 +292,9 @@ _MIGRATE_TO_NEW_RHOCONNECT
288
292
  [res[0], res[1], res[2]]
289
293
  end
290
294
 
291
- # Get random UUID string
292
- def get_random_uuid
293
- UUIDTools::UUID.random_create.to_s.gsub(/\-/,'')
295
+ # Get secure random string
296
+ def get_random_identifier
297
+ SecureRandom.hex
294
298
  end
295
299
 
296
300
  # Generates new token (64-bit integer) based on # of
@@ -1,4 +1,3 @@
1
- require 'uuidtools'
2
1
  module Rhoconnect
3
2
  class ApiToken < StoreOrm
4
3
  field :value,:string
@@ -6,7 +5,7 @@ module Rhoconnect
6
5
  validates_presence_of :user_id
7
6
 
8
7
  def self.create(fields)
9
- fields[:value] = fields[:value] || get_random_uuid
8
+ fields[:value] = fields[:value] || get_random_identifier
10
9
  fields[:id] = fields[:value]
11
10
  super(fields)
12
11
  end
@@ -44,7 +44,7 @@ module Rhoconnect
44
44
 
45
45
  def self.create(fields,params={})
46
46
  Rhoconnect.license.check_and_use_seat
47
- fields[:id] ||= get_random_uuid
47
+ fields[:id] ||= get_random_identifier
48
48
  res = super(fields,params)
49
49
  user = User.load(fields[:user_id])
50
50
  user.clients << res.id
@@ -11,7 +11,7 @@ module Rhoconnect
11
11
  Rhoconnect::DefaultServer.helpers Rhoconnect::Controller::JsBaseHelpers
12
12
 
13
13
  helpers Rhoconnect::Controller::JsBaseHelpers
14
- register Rhoconnect::Handler::PluginCallbacks
14
+ #register Rhoconnect::Handler::PluginCallbacks
15
15
 
16
16
  # source name is available inherently from controller
17
17
  before do
@@ -32,6 +32,11 @@ module Rhoconnect
32
32
  Rhoconnect.add_to_url_map(klass)
33
33
  process_defaults(klass,val['defaults'])
34
34
  process_routes(klass,val['routes'])
35
+
36
+ # add PluginCallback routes (but only for Adapter Controllers)
37
+ unless controller_name == "ApplicationController"
38
+ klass.register Rhoconnect::Handler::PluginCallbacks
39
+ end
35
40
  end
36
41
  end
37
42
 
@@ -74,7 +79,7 @@ module Rhoconnect
74
79
  :route => 'request'
75
80
  }
76
81
  json[:user] = @model.current_user.login if @model
77
- return_value = NodeChannel.publish_channel_and_wait(json,@model)
82
+ return_value = NodeChannel.publish_channel_and_wait(json,@model || self)
78
83
  if finish_block
79
84
  self.send(finish_block, return_value)
80
85
  else
@@ -123,7 +123,7 @@ module Rhoconnect
123
123
  end
124
124
 
125
125
  def before_query
126
- @tmp_docname = :md.to_s + get_random_uuid
126
+ @tmp_docname = :md.to_s + get_random_identifier
127
127
  @stash_size = 0
128
128
  end
129
129
 
@@ -0,0 +1,12 @@
1
+ var app = require('ballroom');
2
+ var rc_helpers = require('rhoconnect_helpers');
3
+ //var RhoInternalJsBenchAdapter = require('../../models/js/rho_internal_js_bench_adapter');
4
+
5
+ app.controllerName('RhoInternalJsBenchAdapter');
6
+ app.registerHandler('sync');
7
+
8
+ // app.post('/',{}, function(req,resp){
9
+ // console.log("inside of controller post");
10
+ // var result = {'id':req.params};
11
+ // resp.send(result);
12
+ // });
@@ -0,0 +1,107 @@
1
+ var rc = require('rhoconnect_helpers');
2
+ var Store = rc.Store;
3
+
4
+ var RhoInternalJsBenchAdapter = function() {
5
+
6
+ this.query = function(resp){
7
+ rc.source(resp,function(resp){
8
+ var source = resp.result;
9
+ var result;
10
+ var db_name = get_db_name(source);
11
+ resp.params = db_name;
12
+ if(source.simulate_time > 0){
13
+ setTimeout(rc.Store.getData(resp,function(resp){
14
+ resp.send(resp.result);
15
+ }), source.simulate_time);
16
+ }
17
+ else{
18
+ rc.Store.getData(resp,function(resp){
19
+ resp.send(resp.result);
20
+ });
21
+ }
22
+ });
23
+ };
24
+
25
+ this.create = function(resp){
26
+ var hsh = resp.params.create_object;
27
+ var mockId2 = hsh["mock_id"];
28
+ rc.source(resp,function(resp){
29
+ var source = resp.result;
30
+ var create_hash = {}
31
+ create_hash[mockId2] = hsh;
32
+ var p = [get_db_name(source),create_hash,true];
33
+ resp.params = p;
34
+ rc.Store.putData(resp,function(resp){
35
+ console.log(JSON.stringify(resp));
36
+ resp.send(mockId2);
37
+ });
38
+ });
39
+ };
40
+
41
+ this.update = function(resp){
42
+ var id = resp.params["id"];
43
+ var update_hash = resp.params["update_object"];
44
+
45
+ rc.source(resp,function(resp){
46
+ var source = resp.result;
47
+ var db = get_db_name(source);
48
+ resp.params = db;
49
+ rc.Store.getData(resp,function(resp){
50
+ var data = resp.result;
51
+ //console.log("data_raw is"+JSON.stringify(data));
52
+ if(data == null || JSON.stringify(data) === "{}"){
53
+ new rc.Exception(resp, 'there is no data to update.');
54
+ }
55
+ for(var key in update_hash){
56
+ data[id][key] = update_hash[key];
57
+ }
58
+ //console.log("data is"+JSON.stringify(data));
59
+ resp.params = [db,data];
60
+ rc.Store.putData(resp,function(resp){
61
+ resp.send(id);
62
+ });
63
+ });
64
+
65
+ });
66
+ };
67
+
68
+ this.del = function(resp){
69
+ var id = resp.params["id"];
70
+ var delete_hash = resp.params["delete_object"];
71
+ rc.source(resp,function(resp){
72
+ var source = resp.result;
73
+ var del_obj = {}
74
+ del_obj[id] = delete_hash
75
+ resp.params = [get_db_name(source),del_obj];
76
+ rc.Store.deleteData(resp,function(resp){
77
+ resp.send(id);
78
+ });
79
+ });
80
+ };
81
+
82
+ this.login = function(resp){
83
+ resp.send(true);
84
+ };
85
+
86
+ this.logoff = function(resp){
87
+ resp.send(true);
88
+ };
89
+
90
+ this.sync = function(resp){
91
+ console.log("called sync");
92
+ };
93
+
94
+
95
+ function get_db_name(source){
96
+ var res;
97
+ if(source.user_id.substring(0,2) == 'nq')
98
+ res = "test_db_storage:"+source.app_id + ":nquser";
99
+ else if(source.user_id.substring(0,2) == 'mq')
100
+ res = "test_db_storage:"+source.app_id+":mquser";
101
+ else
102
+ res = "test_db_storage:"+source.app_id+":benchuser";
103
+ return res;
104
+ }
105
+
106
+ };
107
+ module.exports = new RhoInternalJsBenchAdapter();
@@ -124,6 +124,11 @@ module Rhoconnect
124
124
  update_fields(fields)
125
125
  end
126
126
 
127
+ def to_hash
128
+ res = super
129
+ res.merge({:user_id=>self.user_id,:app_id=>self.app_id})
130
+ end
131
+
127
132
  def self.set_defaults(fields)
128
133
  fields[:url] ||= ''
129
134
  fields[:login] ||= ''
@@ -874,11 +874,13 @@ module Rhoconnect
874
874
  def _get_redis(server=nil)
875
875
  url = ENV[REDIS_URL] || ENV[REDISTOGO_URL] || nil
876
876
  if url
877
+ Rhoconnect.redis_url = url
877
878
  ConnectionPool::Wrapper.new(:size => Rhoconnect.connection_pool_size,
878
879
  :timeout => Rhoconnect.connection_pool_timeout) do
879
880
  Redis.connect(:url => url, :timeout => Rhoconnect.redis_timeout, :thread_safe => true)
880
881
  end
881
882
  elsif server and server.is_a?(String)
883
+ Rhoconnect.redis_url = "redis://#{server}"
882
884
  host,port,db,password = server.split(':')
883
885
  ConnectionPool::Wrapper.new(:size => Rhoconnect.connection_pool_size,
884
886
  :timeout => Rhoconnect.connection_pool_timeout) do
@@ -888,6 +890,7 @@ module Rhoconnect
888
890
  elsif server and (server.is_a?(Redis) or server.is_a?(ConnectionPool::Wrapper))
889
891
  server
890
892
  else
893
+ Rhoconnect.redis_url = "redis://localhost:6379"
891
894
  ConnectionPool::Wrapper.new(:size => 5, :timeout => 30) do
892
895
  Redis.connect(:timeout => 30, :thread_safe => true)
893
896
  end
@@ -1,3 +1,3 @@
1
1
  module Rhoconnect
2
- VERSION = '4.0.0'
2
+ VERSION = '4.0.1'
3
3
  end
@@ -30,8 +30,7 @@ module RhoconnectConsole
30
30
  @token = session[:token] if ENV['INSTANCE_ID']
31
31
  @heroku = RestClient.get('http://nav.heroku.com/v1/providers/header') if @token
32
32
  @version = Rhoconnect::VERSION
33
- @domain = ENV['RHODES_URL'] || request.host_with_port
34
- @domain += "/application" if @domain and !ENV['RHODES_URL']
33
+ @domain = "#{request.scheme}://#{request.host_with_port}"
35
34
  erb :index
36
35
  end
37
36
 
@@ -45,7 +45,6 @@ Gem::Specification.new do |s|
45
45
  s.add_dependency('rake', '~> 10.0.0')
46
46
  s.add_dependency('json', '~> 1.7.7')
47
47
  s.add_dependency('rubyzip', '~> 0.9.4')
48
- s.add_dependency('uuidtools', '>= 2.1.1')
49
48
  s.add_dependency('connection_pool', '~> 1.0.0')
50
49
  s.add_dependency('redis', '>= 3.0.1')
51
50
  s.add_dependency('resque', '>= 1.22.0')
@@ -0,0 +1 @@
1
+ # Dummy Rakefile for testing...
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rhoconnect/application/init'
3
+
4
+ # secret is generated along with the app
5
+ Rhoconnect::Server.set :secret, 'not a secret'
6
+
7
+ # !!! Add your custom initializers and overrides here !!!
8
+ # For example, uncomment the following line to enable Stats
9
+ #Rhoconnect::Server.enable :stats
10
+ # uncomment the following line to disable Resque Front-end console
11
+ #Rhoconnect.disable_resque_console = true
12
+ # uncomment the following line to disable Rhoconnect Front-end console
13
+ #Rhoconnect.disable_rc_console = true
14
+
15
+ # run RhoConnect Application
16
+ run Rhoconnect.app
@@ -0,0 +1,18 @@
1
+ var app = require('ballroom');
2
+ var rc = require('rhoconnect_helpers');
3
+ var Store = rc.Store;
4
+ app.controllerName('Application');
5
+
6
+ app.post('/login',{'rc_handler':'authenticate'}, function(req,resp){
7
+ console.log("inside application_controller.js");
8
+ var login = req.params.login;
9
+ var password = req.params.password;
10
+ if(login === 'storeapitest') {
11
+ resp.params = ['loginkey',login]
12
+ Store.putValue(resp, function(resp){
13
+ resp.send(true);
14
+ });
15
+ } else {
16
+ resp.send(true);
17
+ }
18
+ });
@@ -0,0 +1 @@
1
+ 858fc60fadfde40273d0ac505906969318aa4931d1a2c4aeb24d98393c74379f60e226651601969874257f7f1fbda9b099ecd551a641519aa46819947fda0191
@@ -0,0 +1,13 @@
1
+ :sources:
2
+ :development:
3
+ :licensefile: settings/license.key
4
+ :redis: localhost:6379
5
+ :syncserver: http://localhost:9292/
6
+ :test:
7
+ :licensefile: settings/license.key
8
+ :redis: localhost:6379
9
+ :syncserver: http://localhost:9292/
10
+ :production:
11
+ :licensefile: settings/license.key
12
+ :redis: localhost:6379
13
+ :syncserver: http://localhost:9292/
@@ -8,113 +8,145 @@ describe "Rhoconnect::Controller::JsBase" do
8
8
 
9
9
  it_behaves_like "SharedRhoconnectHelper", :rhoconnect_data => true do
10
10
  def app
11
- @app ||= Rack::URLMap.new Rhoconnect.url_map
11
+ @app = Rack::URLMap.new Rhoconnect.url_map
12
12
  end
13
13
 
14
- before(:each) do
15
- Rhoconnect::Server.set :environment, :test
16
- Rhoconnect::Server.set :secret, "secure!"
17
- Rhoconnect.use_node = true
18
- Rhoconnect.bootstrap(get_testapp_path)
19
- do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'testpass'
20
- end
21
-
22
- after(:each) do
23
- Rhoconnect::Node.kill_process
24
- end
25
-
26
- it "should get / of js controller with route overridden" do
27
- get '/app/v1/JsSample', {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
28
- last_response.should be_ok
29
- body = JSON.parse(last_response.body)
30
- body[2]['count'].should == 1
31
- body.last['insert'].should == {'1' => {'name' => 'iPhone'}}
32
- end
33
-
34
- it "should get /custom_route of js controller" do
35
- get '/app/v1/JsSample/custom_route', {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
36
- last_response.body.should == 'testuser'
37
- end
38
-
39
- it "should get /source from custom route" do
40
- get '/app/v1/JsSample/custom_route2', {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
41
- last_response.body.should == 'JsSample'
42
- end
43
-
44
- it "should get stash_result from js model" do
45
- pending "stash_result not supported yet"
46
- get '/app/v1/JsSample/custom_route3',{}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
47
- res = JSON.parse(last_response.body)
48
- res[2]["count"].should == 1
14
+ def remove_application_controller
15
+ Object.send(:remove_const, :ApplicationController) rescue nil
49
16
  end
50
17
 
51
- it "should register sync route" do
52
- get '/app/v1/Sample2', {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
53
- res = JSON.parse(last_response.body)
54
- res[2]["count"].should == 1
18
+ after(:all) do
19
+ Rhoconnect.use_node = false
55
20
  end
56
21
 
57
- it "should post to js controller" do
58
- hsh = {'1'=>{'name'=>'testname','price'=>'$199'}}
59
- post '/app/v1/JsSample',hsh, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
60
- last_response.should be_ok
61
- end
62
-
63
- it "should put to js controller" do
64
- put '/app/v1/JsSample/2', {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
65
- last_response.body.should == ''
66
- end
67
-
68
- it "should delete to js controller" do
69
- @c1 = Client.create({:user_id => @u.id,:app_id => @a.id},{:source_name => 'JsSample'})
70
- set_doc_state(@c1, :cd => @data)
71
- delete '/app/v1/JsSample/2', {}, {Rhoconnect::CLIENT_ID_HEADER => @c1.id}
72
- last_response.should be_ok
73
- end
74
-
75
- it "should call route that overrides default option" do
76
- get '/app/v1/JsSample/no_client_route', {}
77
- last_response.should be_ok
78
- last_response.body.should == 'no client required!'
79
- end
80
-
81
- it "should upload blob in multipart post" do
82
- file1,file2 = 'upload1.txt'
83
- @product1['txtfile-rhoblob'] = file1
84
- @product1['_id'] = 'tempobj1'
85
- cud = {'create'=>{'1'=>{'name'=>'hello'}},
86
- :blob_fields => ['txtfile-rhoblob']}.to_json
87
- post "/app/#{Rhoconnect::API_VERSION}/JsSample",
88
- {:cud => cud,'txtfile-rhoblob-1' =>
89
- Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__),'..','testdata',file1), "application/octet-stream")},
90
- {Rhoconnect::CLIENT_ID_HEADER => @c.id}
91
- last_response.should be_ok
92
- get "/app/#{Rhoconnect::API_VERSION}/JsSample", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
93
- json = JSON.parse(last_response.body)
94
- json[5]['links'].should == { "1" => { "l" => "blob_created" } }
95
- json[5]['delete'].should == { "blob_created" => { "name" => "hello", "txtfile-rhoblob" => "blob_created" } }
22
+ def bootstrap_rhoconnect(jsapp = false)
23
+ Rhoconnect::Server.set :environment, :test
24
+ Rhoconnect::Server.set :secret, "secure!"
25
+ Rhoconnect.use_node = true
26
+ if jsapp
27
+ Rhoconnect.bootstrap(get_jstestapp_path)
28
+ else
29
+ Rhoconnect.bootstrap(get_testapp_path)
30
+ end
31
+ # reload ruby controllers
32
+ Dir[File.join(Rhoconnect.app_directory,'controllers','ruby','*.rb')].each do |controller_file|
33
+ load controller_file
34
+ end
96
35
  end
97
36
 
98
- it "should push_objects to js controller" do
99
- s = Source.load('JsSample', @s_params)
100
- data = {'1' => @product1, '2' => @product2, '3' => @product3}
101
- post "/app/#{Rhoconnect::API_VERSION}/JsSample/push_objects",
102
- {:user_id => @u.id, :objects => data}, {Rhoconnect::API_TOKEN_HEADER => @api_token}
103
- last_response.should be_ok
104
- verify_doc_result(s, {:md => data, :md_size=>'3'})
37
+ describe "ApplicationController" do
38
+ after(:each) do
39
+ Rhoconnect.remove_from_url_map(ApplicationController)
40
+ remove_application_controller
41
+ end
42
+
43
+ it "should call Store api in ApplicationController" do
44
+ Rhoconnect.remove_from_url_map(ApplicationController)
45
+ remove_application_controller
46
+ bootstrap_rhoconnect(true)
47
+ do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => 'storeapitest', "password" => 'testpass'
48
+ Store.get_value('loginkey').should == 'storeapitest'
49
+ end
105
50
  end
106
51
 
107
- it "should push_deletes to js controller" do
108
- data = {'1' => @product1, '2' => @product2, '3' => @product3}
109
- s = Source.load('JsSample',@s_params)
110
- set_doc_state(s, {:md => data, :md_size => '3'})
111
- data.delete('2')
112
- post "/app/#{Rhoconnect::API_VERSION}/JsSample/push_deletes",
113
- {:user_id => @u.id, :objects => ['2']}, {Rhoconnect::API_TOKEN_HEADER => @api_token}
114
- last_response.should be_ok
115
- verify_doc_result(s, {:md => data, :md_size=>'2'})
52
+ describe "Named Controller" do
53
+
54
+ before(:each) do
55
+ bootstrap_rhoconnect
56
+ do_post "/rc/#{Rhoconnect::API_VERSION}/app/login", "login" => @u.login, "password" => 'testpass'
57
+ end
58
+
59
+ it "should get / of js controller with route overridden" do
60
+ get '/app/v1/JsSample', {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
61
+ last_response.should be_ok
62
+ body = JSON.parse(last_response.body)
63
+ body[2]['count'].should == 1
64
+ body.last['insert'].should == {'1' => {'name' => 'iPhone'}}
65
+ end
66
+
67
+ it "should get /custom_route of js controller" do
68
+ get '/app/v1/JsSample/custom_route', {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
69
+ last_response.body.should == 'testuser'
70
+ end
71
+
72
+ it "should get /source from custom route" do
73
+ get '/app/v1/JsSample/custom_route2', {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
74
+ last_response.body.should == 'JsSample'
75
+ end
76
+
77
+ it "should get stash_result from js model" do
78
+ pending "stash_result not supported yet"
79
+ get '/app/v1/JsSample/custom_route3',{}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
80
+ res = JSON.parse(last_response.body)
81
+ res[2]["count"].should == 1
82
+ end
83
+
84
+ it "should register sync route" do
85
+ get '/app/v1/Sample2', {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
86
+ res = JSON.parse(last_response.body)
87
+ res[2]["count"].should == 1
88
+ end
89
+
90
+ it "should post to js controller" do
91
+ hsh = {'1'=>{'name'=>'testname','price'=>'$199'}}
92
+ post '/app/v1/JsSample',hsh, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
93
+ last_response.should be_ok
94
+ end
95
+
96
+ it "should put to js controller" do
97
+ put '/app/v1/JsSample/2', {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
98
+ last_response.body.should == ''
99
+ end
100
+
101
+ it "should delete to js controller" do
102
+ @c1 = Client.create({:user_id => @u.id,:app_id => @a.id},{:source_name => 'JsSample'})
103
+ set_doc_state(@c1, :cd => @data)
104
+ delete '/app/v1/JsSample/2', {}, {Rhoconnect::CLIENT_ID_HEADER => @c1.id}
105
+ last_response.should be_ok
106
+ end
107
+
108
+ it "should call route that overrides default option" do
109
+ get '/app/v1/JsSample/no_client_route', {}
110
+ last_response.should be_ok
111
+ last_response.body.should == 'no client required!'
112
+ end
113
+
114
+ it "should upload blob in multipart post" do
115
+ file1,file2 = 'upload1.txt'
116
+ @product1['txtfile-rhoblob'] = file1
117
+ @product1['_id'] = 'tempobj1'
118
+ cud = {'create'=>{'1'=>{'name'=>'hello'}},
119
+ :blob_fields => ['txtfile-rhoblob']}.to_json
120
+ post "/app/#{Rhoconnect::API_VERSION}/JsSample",
121
+ {:cud => cud,'txtfile-rhoblob-1' =>
122
+ Rack::Test::UploadedFile.new(File.join(File.dirname(__FILE__),'..','testdata',file1), "application/octet-stream")},
123
+ {Rhoconnect::CLIENT_ID_HEADER => @c.id}
124
+ last_response.should be_ok
125
+ get "/app/#{Rhoconnect::API_VERSION}/JsSample", {}, {Rhoconnect::CLIENT_ID_HEADER => @c.id}
126
+ json = JSON.parse(last_response.body)
127
+ json[5]['links'].should == { "1" => { "l" => "blob_created" } }
128
+ json[5]['delete'].should == { "blob_created" => { "name" => "hello", "txtfile-rhoblob" => "blob_created" } }
129
+ end
130
+
131
+ it "should push_objects to js controller" do
132
+ s = Source.load('JsSample', @s_params)
133
+ data = {'1' => @product1, '2' => @product2, '3' => @product3}
134
+ post "/app/#{Rhoconnect::API_VERSION}/JsSample/push_objects",
135
+ {:user_id => @u.id, :objects => data}, {Rhoconnect::API_TOKEN_HEADER => @api_token}
136
+ last_response.should be_ok
137
+ verify_doc_result(s, {:md => data, :md_size=>'3'})
138
+ end
139
+
140
+ it "should push_deletes to js controller" do
141
+ data = {'1' => @product1, '2' => @product2, '3' => @product3}
142
+ s = Source.load('JsSample',@s_params)
143
+ set_doc_state(s, {:md => data, :md_size => '3'})
144
+ data.delete('2')
145
+ post "/app/#{Rhoconnect::API_VERSION}/JsSample/push_deletes",
146
+ {:user_id => @u.id, :objects => ['2']}, {Rhoconnect::API_TOKEN_HEADER => @api_token}
147
+ last_response.should be_ok
148
+ verify_doc_result(s, {:md => data, :md_size=>'2'})
149
+ end
116
150
  end
117
-
118
- it "should register deprecated_route"
119
151
  end
120
152
  end