render_sync 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +153 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +22 -0
  5. data/README.md +521 -0
  6. data/Rakefile +9 -0
  7. data/app/assets/javascripts/sync.coffee +355 -0
  8. data/app/controllers/sync/refetches_controller.rb +56 -0
  9. data/app/helpers/render_sync/config_helper.rb +15 -0
  10. data/config/routes.rb +3 -0
  11. data/config/sync.yml +21 -0
  12. data/lib/generators/render_sync/install_generator.rb +14 -0
  13. data/lib/generators/render_sync/templates/sync.ru +14 -0
  14. data/lib/generators/render_sync/templates/sync.yml +34 -0
  15. data/lib/render_sync.rb +174 -0
  16. data/lib/render_sync/action.rb +39 -0
  17. data/lib/render_sync/actions.rb +114 -0
  18. data/lib/render_sync/channel.rb +23 -0
  19. data/lib/render_sync/clients/dummy.rb +22 -0
  20. data/lib/render_sync/clients/faye.rb +104 -0
  21. data/lib/render_sync/clients/pusher.rb +77 -0
  22. data/lib/render_sync/controller_helpers.rb +33 -0
  23. data/lib/render_sync/engine.rb +24 -0
  24. data/lib/render_sync/erb_tracker.rb +49 -0
  25. data/lib/render_sync/faye_extension.rb +45 -0
  26. data/lib/render_sync/model.rb +174 -0
  27. data/lib/render_sync/model_actions.rb +60 -0
  28. data/lib/render_sync/model_change_tracking.rb +97 -0
  29. data/lib/render_sync/model_syncing.rb +65 -0
  30. data/lib/render_sync/model_touching.rb +35 -0
  31. data/lib/render_sync/partial.rb +112 -0
  32. data/lib/render_sync/partial_creator.rb +47 -0
  33. data/lib/render_sync/reactor.rb +48 -0
  34. data/lib/render_sync/refetch_model.rb +21 -0
  35. data/lib/render_sync/refetch_partial.rb +43 -0
  36. data/lib/render_sync/refetch_partial_creator.rb +21 -0
  37. data/lib/render_sync/renderer.rb +19 -0
  38. data/lib/render_sync/resource.rb +115 -0
  39. data/lib/render_sync/scope.rb +113 -0
  40. data/lib/render_sync/scope_definition.rb +30 -0
  41. data/lib/render_sync/view_helpers.rb +106 -0
  42. data/test/dummy/README.rdoc +28 -0
  43. data/test/dummy/Rakefile +6 -0
  44. data/test/dummy/app/assets/javascripts/application.js +13 -0
  45. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  46. data/test/dummy/app/controllers/application_controller.rb +5 -0
  47. data/test/dummy/app/helpers/application_helper.rb +2 -0
  48. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  49. data/test/dummy/app/views/sync/users/_show.html.erb +1 -0
  50. data/test/dummy/app/views/sync/users/refetch/_show.html.erb +1 -0
  51. data/test/dummy/bin/bundle +3 -0
  52. data/test/dummy/bin/rails +4 -0
  53. data/test/dummy/bin/rake +4 -0
  54. data/test/dummy/config.ru +4 -0
  55. data/test/dummy/config/application.rb +22 -0
  56. data/test/dummy/config/boot.rb +5 -0
  57. data/test/dummy/config/database.yml +8 -0
  58. data/test/dummy/config/environment.rb +5 -0
  59. data/test/dummy/config/environments/development.rb +29 -0
  60. data/test/dummy/config/environments/production.rb +80 -0
  61. data/test/dummy/config/environments/test.rb +36 -0
  62. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  63. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  64. data/test/dummy/config/initializers/inflections.rb +16 -0
  65. data/test/dummy/config/initializers/mime_types.rb +5 -0
  66. data/test/dummy/config/initializers/secret_token.rb +12 -0
  67. data/test/dummy/config/initializers/session_store.rb +3 -0
  68. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  69. data/test/dummy/config/locales/en.yml +23 -0
  70. data/test/dummy/config/routes.rb +56 -0
  71. data/test/dummy/log/test.log +626 -0
  72. data/test/dummy/public/404.html +58 -0
  73. data/test/dummy/public/422.html +58 -0
  74. data/test/dummy/public/500.html +57 -0
  75. data/test/dummy/public/favicon.ico +0 -0
  76. data/test/em_minitest_spec.rb +100 -0
  77. data/test/fixtures/sync_auth_token_missing.yml +6 -0
  78. data/test/fixtures/sync_erb.yml +7 -0
  79. data/test/fixtures/sync_faye.yml +7 -0
  80. data/test/fixtures/sync_pusher.yml +8 -0
  81. data/test/models/group.rb +3 -0
  82. data/test/models/project.rb +2 -0
  83. data/test/models/todo.rb +8 -0
  84. data/test/models/user.rb +82 -0
  85. data/test/sync/abstract_controller.rb +3 -0
  86. data/test/sync/action_test.rb +82 -0
  87. data/test/sync/channel_test.rb +15 -0
  88. data/test/sync/config_test.rb +25 -0
  89. data/test/sync/erb_tracker_test.rb +72 -0
  90. data/test/sync/faye_extension_test.rb +87 -0
  91. data/test/sync/message_test.rb +159 -0
  92. data/test/sync/model_test.rb +315 -0
  93. data/test/sync/partial_creator_test.rb +35 -0
  94. data/test/sync/partial_test.rb +107 -0
  95. data/test/sync/protected_attributes_test.rb +39 -0
  96. data/test/sync/reactor_test.rb +18 -0
  97. data/test/sync/refetch_model_test.rb +26 -0
  98. data/test/sync/refetch_partial_creator_test.rb +16 -0
  99. data/test/sync/refetch_partial_test.rb +74 -0
  100. data/test/sync/renderer_test.rb +19 -0
  101. data/test/sync/resource_test.rb +181 -0
  102. data/test/sync/scope_definition_test.rb +39 -0
  103. data/test/sync/scope_test.rb +113 -0
  104. data/test/test_helper.rb +66 -0
  105. data/test/travis/sync.ru +14 -0
  106. data/test/travis/sync.yml +21 -0
  107. metadata +317 -0
@@ -0,0 +1,35 @@
1
+ require_relative '../test_helper'
2
+
3
+ describe RenderSync::PartialCreator do
4
+ include TestHelper
5
+
6
+ before do
7
+ @context = ActionController::Base.new
8
+ @partial_creator = RenderSync::PartialCreator.new("show", User.new, scope = nil, @context)
9
+ end
10
+
11
+ describe '#channel' do
12
+ it 'always starts with a forward slash to provide Faye valid channel' do
13
+ assert_equal "/", @partial_creator.channel.first
14
+ end
15
+ end
16
+
17
+ describe '#selector' do
18
+ it 'returns a String selector where partials will be appended in DOM' do
19
+ assert @partial_creator.selector.length > 0
20
+ end
21
+ end
22
+
23
+ describe '#sync_new' do
24
+ it 'publishes a new message to faye to append new partials to DOM' do
25
+ # TODO: Stub Message
26
+ assert @partial_creator.sync_new
27
+ end
28
+ end
29
+
30
+ describe '#message' do
31
+ it 'returns a Message instance for the partial for the update action' do
32
+ assert_equal RenderSync.client.class::Message, @partial_creator.message.class
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,107 @@
1
+ require_relative '../test_helper'
2
+ require 'rails/all'
3
+ require_relative 'abstract_controller'
4
+ require_relative '../models/user'
5
+
6
+ describe RenderSync::Partial do
7
+ include TestHelper
8
+
9
+ before do
10
+ @context = ActionController::Base.new
11
+ @partial = RenderSync::Partial.new("show", User.new, nil, @context)
12
+ end
13
+
14
+ describe '#self.all' do
15
+ it 'returns an array of all Partials for given model' do
16
+ assert_equal 1, RenderSync::Partial.all(User.new, @context).size
17
+ assert_equal RenderSync::Partial, RenderSync::Partial.all(User.new, @context)[0].class
18
+ end
19
+ end
20
+
21
+ describe '#self.find' do
22
+ it 'finds partial given resource and partial name' do
23
+ Dir.stubs(:[]).returns("_show.html.erb")
24
+ assert_equal RenderSync::Partial, RenderSync::Partial.find(User.new, 'show', nil).class
25
+ end
26
+
27
+ it 'returns nil if partial does not exist' do
28
+ Dir.stubs(:[]).returns []
29
+ refute RenderSync::Partial.find(User.new, 'not_exist', nil)
30
+ end
31
+ end
32
+
33
+ describe '#render_to_string' do
34
+ it 'renders itself as a string' do
35
+ assert_equal "<h1>1<\/h1>", @partial.render_to_string
36
+ end
37
+ end
38
+
39
+ describe '#render' do
40
+ it 'renders' do
41
+ # TODO stub out
42
+ assert @partial.respond_to?(:render)
43
+ end
44
+ end
45
+
46
+ describe '#sync' do
47
+ it 'sends update to faye for given partial and update action' do
48
+ # TODO stub out
49
+ assert @partial.sync(:update)
50
+ end
51
+
52
+ it 'sends update to faye for given partial and destroy action' do
53
+ # TODO stub out
54
+ assert @partial.sync(:destroy)
55
+ end
56
+ end
57
+
58
+ describe '#message' do
59
+ it 'returns a Message instance for the partial for the update action' do
60
+ assert_equal RenderSync.client.class::Message, @partial.message(:update).class
61
+ end
62
+
63
+ it 'returns a Message instance for the partial for the destroy action' do
64
+ assert_equal RenderSync.client.class::Message, @partial.message(:destroy).class
65
+ end
66
+ end
67
+
68
+ describe '#channel_prefix' do
69
+ it 'returns a unique channel prefix for the partial given its name and resource' do
70
+ assert @partial.channel_prefix
71
+ end
72
+ end
73
+
74
+ describe 'channel_for_action' do
75
+ it 'returns the channel for the update action' do
76
+ assert @partial.channel_for_action(:update)
77
+ end
78
+
79
+ it 'returns the channel for the destroy action' do
80
+ assert @partial.channel_for_action(:destroy)
81
+ end
82
+
83
+ it 'always starts with a forward slash to provide Faye valid channel' do
84
+ assert_equal "/", @partial.channel_for_action(:update).first
85
+ assert_equal "/", @partial.channel_for_action(:destroy).first
86
+ end
87
+ end
88
+
89
+ describe '#selector_start' do
90
+ it 'returns a string for the selector to mark element beginning' do
91
+ assert @partial.selector_start.present?
92
+ end
93
+ end
94
+
95
+ describe '#selector_end' do
96
+ it 'returns a string for the selector to mark element ending' do
97
+ assert @partial.selector_end.present?
98
+ end
99
+ end
100
+
101
+ describe 'creator_for_scope' do
102
+ it 'returns a new PartialCreator for given scope' do
103
+ assert_equal RenderSync::PartialCreator, @partial.creator_for_scope(nil).class
104
+ assert @partial, @partial.creator_for_scope(nil).partial
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,39 @@
1
+ require_relative '../test_helper'
2
+ require 'mocha/setup'
3
+ require 'rails/all'
4
+
5
+ setup_database
6
+
7
+ describe RenderSync::Model do
8
+
9
+ it 'publishes record (create/update/destroy) to main new channel' do
10
+ RenderSync::Model.enable do
11
+ user = UserWithProtectedAttributes.new
12
+
13
+ # Create
14
+ user.save!
15
+ assert user.persisted?
16
+ assert_equal 1, user.sync_actions.size
17
+
18
+ assert_equal :new, user.sync_actions[0].name
19
+ assert_equal "/user_with_protected_attributes/#{user.id}", user.sync_actions[0].test_path
20
+
21
+ # Update
22
+ user.update_attribute(:name, "Foo")
23
+ assert user.persisted?
24
+ assert_equal 1, user.sync_actions.size
25
+
26
+ assert_equal :update, user.sync_actions[0].name
27
+ assert_equal "/user_with_protected_attributes/#{user.id}", user.sync_actions[0].test_path
28
+
29
+ # Destroy
30
+ user.destroy
31
+ assert user.destroyed?
32
+ assert_equal 1, user.sync_actions.size
33
+
34
+ assert_equal :destroy, user.sync_actions[0].name
35
+ assert_equal "/user_with_protected_attributes/#{user.id}", user.sync_actions[0].test_path
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,18 @@
1
+ require_relative '../test_helper'
2
+ require 'mocha/setup'
3
+
4
+
5
+ describe RenderSync::Reactor do
6
+ include TestHelper
7
+
8
+ describe '#perform' do
9
+ it 'starts EventMachine thread and runs block' do
10
+ refute RenderSync.reactor.running?
11
+ ran_block = false
12
+ RenderSync.reactor.perform { ran_block = true}
13
+ assert RenderSync.reactor.running?
14
+ sleep 0.1
15
+ assert ran_block
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ require_relative '../test_helper'
2
+ require_relative '../models/user'
3
+ require 'mocha/setup'
4
+
5
+ describe RenderSync::RefetchModel do
6
+ include TestHelper
7
+
8
+ describe '#find_by_class_name_and_id' do
9
+ it 'finds record by model name and id' do
10
+ User.expects(:find).once.returns(User.new)
11
+ RenderSync::RefetchModel.stubs(:supported_classes).returns ["User"]
12
+ assert RenderSync::RefetchModel.find_by_class_name_and_id("user", 1).is_a? User
13
+ end
14
+
15
+ it 'Returns nil if class name is not sync model' do
16
+ Object.expects(:find).never
17
+ refute RenderSync::RefetchModel.find_by_class_name_and_id("object", 1)
18
+ end
19
+
20
+ it "Returns nil if record is not found for id" do
21
+ User.expects(:find).once.raises(StandardError.new("Record not found"))
22
+ RenderSync::RefetchModel.stubs(:supported_classes).returns ["User"]
23
+ refute RenderSync::RefetchModel.find_by_class_name_and_id("user", 1)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ require_relative '../test_helper'
2
+
3
+ describe RenderSync::RefetchPartialCreator do
4
+ include TestHelper
5
+
6
+ before do
7
+ @context = ActionController::Base.new
8
+ @partial_creator = RenderSync::RefetchPartialCreator.new("show", User.new, scope = nil, @context)
9
+ end
10
+
11
+ describe '#message' do
12
+ it 'returns a Message instance for the partial for the update action' do
13
+ assert_equal RenderSync.client.class::Message, @partial_creator.message.class
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,74 @@
1
+ require_relative '../test_helper'
2
+ require 'rails/all'
3
+ require_relative 'abstract_controller'
4
+ require_relative '../models/user'
5
+
6
+ describe RenderSync::RefetchPartial do
7
+ include TestHelper
8
+
9
+ before do
10
+ @context = ActionController::Base.new
11
+ @partial = RenderSync::RefetchPartial.new("show", User.new, nil, @context)
12
+ end
13
+
14
+ describe '#self.all' do
15
+ it 'returns an array of all Partials for given model' do
16
+ assert_equal 1, RenderSync::RefetchPartial.all(User.new, @context).size
17
+ assert_equal RenderSync::RefetchPartial, RenderSync::RefetchPartial.all(User.new, @context)[0].class
18
+ end
19
+ end
20
+
21
+ describe '#self.find' do
22
+ it 'finds partial given resource and partial name' do
23
+ assert_equal RenderSync::RefetchPartial, RenderSync::RefetchPartial.find(User.new, 'show', @context).class
24
+ end
25
+
26
+ it 'returns nil if partial does not exist' do
27
+ refute RenderSync::RefetchPartial.find(User.new, 'not_exist', nil)
28
+ end
29
+ end
30
+
31
+ describe '#self.find_by_authorized_resource' do
32
+
33
+ it 'returns partial when given auth token for resource and template' do
34
+ assert_equal RenderSync::RefetchPartial, RenderSync::RefetchPartial.find_by_authorized_resource(
35
+ @partial.resource.model,
36
+ @partial.name,
37
+ nil,
38
+ @partial.auth_token
39
+ ).class
40
+ end
41
+
42
+ it 'returns nil when given invalid auth token for resource and template' do
43
+ refute RenderSync::RefetchPartial.find_by_authorized_resource(
44
+ @partial.resource.model,
45
+ @partial.name,
46
+ nil,
47
+ "invalid auth token"
48
+ )
49
+ end
50
+ end
51
+
52
+ describe '#render_to_string' do
53
+ it 'renders itself as a string from the refetch directory' do
54
+ assert_equal "<h1>Refetch 1<\/h1>", @partial.render_to_string
55
+ end
56
+ end
57
+
58
+ describe '#message' do
59
+ it 'returns a Message instance for the partial for the update action' do
60
+ assert_equal RenderSync.client.class::Message, @partial.message(:update).class
61
+ end
62
+
63
+ it 'returns a Message instance for the partial for the destroy action' do
64
+ assert_equal RenderSync.client.class::Message, @partial.message(:destroy).class
65
+ end
66
+ end
67
+
68
+ describe 'creator_for_scope' do
69
+ it 'returns a new PartialCreator for given scope' do
70
+ assert_equal RenderSync::RefetchPartialCreator, @partial.creator_for_scope(nil).class
71
+ assert @partial, @partial.creator_for_scope(nil).partial
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,19 @@
1
+ require_relative '../test_helper'
2
+ require_relative '../models/user'
3
+
4
+ describe RenderSync::Renderer do
5
+ include TestHelper
6
+
7
+ class ApplicationController < ActionController::Base
8
+ end
9
+
10
+ let(:renderer){ RenderSync::Renderer.new }
11
+
12
+ describe '#render_to_string' do
13
+ it 'renders partial as string' do
14
+ assert_equal "<h1>1<\/h1>", renderer.render_to_string(
15
+ partial: 'sync/users/show', locals: { user: User.new }
16
+ )
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,181 @@
1
+ require 'rails/all'
2
+ require_relative '../test_helper'
3
+ require_relative 'abstract_controller'
4
+ require_relative '../models/user'
5
+ require_relative '../models/project'
6
+ require_relative '../models/group'
7
+
8
+ describe RenderSync::Partial do
9
+ include TestHelper
10
+
11
+ before do
12
+ @user = User.create
13
+ @group = Group.create
14
+ @project = Project.create
15
+ end
16
+
17
+ describe '#name' do
18
+ it 'returns the underscored model class name' do
19
+ assert_equal "user", RenderSync::Resource.new(@user).name
20
+ end
21
+ end
22
+
23
+ describe '#plural_name' do
24
+ it 'returns the underscored model class name' do
25
+ assert_equal "users", RenderSync::Resource.new(@user).plural_name
26
+ end
27
+ end
28
+
29
+ describe '#id' do
30
+ it 'returns the models id' do
31
+ assert_equal 1, RenderSync::Resource.new(@user).id
32
+ end
33
+ end
34
+
35
+ describe '#scopes=' do
36
+ before do
37
+ @resource = RenderSync::Resource.new(@user)
38
+ end
39
+
40
+ it 'ignores nil' do
41
+ @resource.scopes = nil
42
+ assert_nil @resource.scopes
43
+ end
44
+
45
+ it 'converts scalar value to an array' do
46
+ @resource.scopes = :en
47
+ assert_equal [:en], @resource.scopes
48
+ end
49
+
50
+ end
51
+
52
+ describe '#scopes_path' do
53
+ describe 'a resource without a scope' do
54
+ it 'returns /' do
55
+ resource = RenderSync::Resource.new(@user)
56
+ assert_equal '/', resource.scopes_path.to_s
57
+ end
58
+ end
59
+
60
+ describe 'a resource with a simple scope' do
61
+ it 'returns a path prefixed with the scope' do
62
+ resource = RenderSync::Resource.new(@user, :admin)
63
+ assert_equal '/admin', resource.scopes_path.to_s
64
+ end
65
+ end
66
+
67
+ describe 'a resource with a parent model as scope' do
68
+ it "returns the parent model's path" do
69
+ resource = RenderSync::Resource.new(@user, @project)
70
+ assert_equal "/projects/#{@project.id}", resource.scopes_path.to_s
71
+ end
72
+ end
73
+
74
+ describe 'a resource with mixed scopes' do
75
+ it 'returns a path including all scopes' do
76
+ resource = RenderSync::Resource.new(@user, [:en, :admin, @project])
77
+ assert_equal "/en/admin/projects/#{@project.id}", resource.scopes_path.to_s
78
+ end
79
+ end
80
+ end
81
+
82
+ describe '#polymorphic_path' do
83
+ describe 'a resource without a scope' do
84
+ it 'returns the path for the model' do
85
+ assert_equal "/users/1", RenderSync::Resource.new(@user).polymorphic_path.to_s
86
+ end
87
+ end
88
+
89
+ describe 'a resource with a simple scope' do
90
+ it 'returns the path for the model, prefixed by the scope' do
91
+ resource = RenderSync::Resource.new(@user, :en)
92
+ assert_equal "/en/users/1", resource.polymorphic_path.to_s
93
+ end
94
+ end
95
+
96
+ describe 'a resource with a parent model as scope' do
97
+ it 'returns the path for the model, prefixed by parent path' do
98
+ child = RenderSync::Resource.new(@user, @project)
99
+ assert_equal "/projects/#{@project.id}/users/1", child.polymorphic_path.to_s
100
+ end
101
+ end
102
+
103
+ describe 'a resource with an RenderSync::Scope object as scope' do
104
+ it 'returns the path for the model, prefixed by sync_scope path' do
105
+ child = RenderSync::Resource.new(@user, User.cool)
106
+ assert_equal "/cool/users/1", child.polymorphic_path.to_s
107
+ end
108
+ end
109
+
110
+ describe 'a resource with an RenderSync::Scope object with AR-param as scope' do
111
+ it 'returns the path for the model, prefixed by sync_scope path' do
112
+ child = RenderSync::Resource.new(@user, User.in_group(@group))
113
+ assert_equal "/in_group/group/#{@group.id}/users/1", child.polymorphic_path.to_s
114
+ end
115
+ end
116
+
117
+ describe 'a resource with an RenderSync::Scope object with Integer-param as scope' do
118
+ it 'returns the path for the model, prefixed by sync_scope path' do
119
+ child = RenderSync::Resource.new(@user, User.with_group_id(@group.id))
120
+ assert_equal "/with_group_id/group_id/#{@group.id}/users/1", child.polymorphic_path.to_s
121
+ end
122
+ end
123
+
124
+ describe 'a resource with an RenderSync::Scope object with multiple params as scope' do
125
+ it 'returns the path for the model, prefixed by sync_scope path' do
126
+ child = RenderSync::Resource.new(@user, User.with_min_age_in_group(15, @group.id))
127
+ assert_equal "/with_min_age_in_group/age/15/group_id/#{@group.id}/users/1", child.polymorphic_path.to_s
128
+ end
129
+ end
130
+
131
+ describe 'a resource with mixed scopes' do
132
+ it 'returns the path for the model, prefixed by all scopes' do
133
+ child = RenderSync::Resource.new(@user, [:en, :admin, @project, User.cool, User.in_group(@group)])
134
+ assert_equal "/en/admin/projects/#{@project.id}/cool/in_group/group/#{@group.id}/users/1", child.polymorphic_path.to_s
135
+ end
136
+ end
137
+ end
138
+
139
+ describe '#model_path' do
140
+ it 'returns the raw path of the model without any scopes' do
141
+ child = RenderSync::Resource.new(@user, @project)
142
+ assert_equal "/users/1", child.model_path.to_s
143
+ end
144
+ end
145
+
146
+ describe '#polymorphic_new_path' do
147
+ describe 'a resource without a scope' do
148
+ it 'returns the path for the model' do
149
+ assert_equal "/users/new", RenderSync::Resource.new(@user).polymorphic_new_path.to_s
150
+ end
151
+ end
152
+
153
+ describe 'a resource with a simple scope' do
154
+ it 'returns the path for the model, prefixed by the scope' do
155
+ resource = RenderSync::Resource.new(@user, :en)
156
+ assert_equal "/en/users/new", resource.polymorphic_new_path.to_s
157
+ end
158
+ end
159
+
160
+ describe 'a resource with a parent model as scope' do
161
+ it 'returns the path for the model, prefixed by parent path' do
162
+ child = RenderSync::Resource.new(@user, @project)
163
+ assert_equal "/projects/#{@project.id}/users/new", child.polymorphic_new_path.to_s
164
+ end
165
+ end
166
+
167
+ describe 'a resource with a RenderSync::Scope object as scope' do
168
+ it 'returns the path for the model, prefixed by parent path' do
169
+ child = RenderSync::Resource.new(@user, User.cool)
170
+ assert_equal "/cool/users/new", child.polymorphic_new_path.to_s
171
+ end
172
+ end
173
+
174
+ describe 'a resource with mixed scopes' do
175
+ it 'returns the path for the model, prefixed by all scopes' do
176
+ child = RenderSync::Resource.new(@user, [:en, :admin, @project, User.cool, User.in_group(@group)])
177
+ assert_equal "/en/admin/projects/#{@project.id}/cool/in_group/group/#{@group.id}/users/new", child.polymorphic_new_path.to_s
178
+ end
179
+ end
180
+ end
181
+ end