moonrope 1.3.3 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +9 -0
  3. data/Gemfile.lock +47 -0
  4. data/MIT-LICENCE +20 -0
  5. data/README.md +24 -0
  6. data/bin/moonrope +28 -0
  7. data/docs/authentication.md +114 -0
  8. data/docs/controllers.md +106 -0
  9. data/docs/exceptions.md +27 -0
  10. data/docs/introduction.md +29 -0
  11. data/docs/structures.md +214 -0
  12. data/example/authentication.rb +50 -0
  13. data/example/controllers/meta_controller.rb +14 -0
  14. data/example/controllers/users_controller.rb +92 -0
  15. data/example/structures/pet_structure.rb +12 -0
  16. data/example/structures/user_structure.rb +35 -0
  17. data/lib/moonrope.rb +5 -4
  18. data/lib/moonrope/action.rb +170 -40
  19. data/lib/moonrope/authenticator.rb +42 -0
  20. data/lib/moonrope/base.rb +67 -6
  21. data/lib/moonrope/controller.rb +4 -2
  22. data/lib/moonrope/doc_context.rb +94 -0
  23. data/lib/moonrope/doc_server.rb +123 -0
  24. data/lib/moonrope/dsl/action_dsl.rb +159 -9
  25. data/lib/moonrope/dsl/authenticator_dsl.rb +35 -0
  26. data/lib/moonrope/dsl/base_dsl.rb +21 -18
  27. data/lib/moonrope/dsl/controller_dsl.rb +60 -9
  28. data/lib/moonrope/dsl/filterable_dsl.rb +27 -0
  29. data/lib/moonrope/dsl/structure_dsl.rb +28 -2
  30. data/lib/moonrope/errors.rb +13 -0
  31. data/lib/moonrope/eval_environment.rb +82 -3
  32. data/lib/moonrope/eval_helpers.rb +47 -8
  33. data/lib/moonrope/eval_helpers/filter_helper.rb +82 -0
  34. data/lib/moonrope/guard.rb +35 -0
  35. data/lib/moonrope/html_generator.rb +65 -0
  36. data/lib/moonrope/param_set.rb +11 -1
  37. data/lib/moonrope/rack_middleware.rb +66 -37
  38. data/lib/moonrope/railtie.rb +31 -14
  39. data/lib/moonrope/request.rb +43 -15
  40. data/lib/moonrope/structure.rb +100 -18
  41. data/lib/moonrope/structure_attribute.rb +39 -0
  42. data/lib/moonrope/version.rb +1 -1
  43. data/moonrope.gemspec +21 -0
  44. data/spec/spec_helper.rb +32 -0
  45. data/spec/specs/action_spec.rb +455 -0
  46. data/spec/specs/base_spec.rb +29 -0
  47. data/spec/specs/controller_spec.rb +31 -0
  48. data/spec/specs/param_set_spec.rb +31 -0
  49. data/templates/basic/_action_form.erb +77 -0
  50. data/templates/basic/_errors_table.erb +32 -0
  51. data/templates/basic/_structure_attributes_list.erb +55 -0
  52. data/templates/basic/action.erb +168 -0
  53. data/templates/basic/assets/lock.svg +3 -0
  54. data/templates/basic/assets/reset.css +101 -0
  55. data/templates/basic/assets/style.css +348 -0
  56. data/templates/basic/assets/tool.svg +4 -0
  57. data/templates/basic/assets/try.js +157 -0
  58. data/templates/basic/authenticator.erb +52 -0
  59. data/templates/basic/controller.erb +20 -0
  60. data/templates/basic/index.erb +114 -0
  61. data/templates/basic/layout.erb +46 -0
  62. data/templates/basic/structure.erb +23 -0
  63. data/test/test_helper.rb +81 -0
  64. data/test/tests/action_access_test.rb +63 -0
  65. data/test/tests/actions_test.rb +524 -0
  66. data/test/tests/authenticators_test.rb +87 -0
  67. data/test/tests/base_test.rb +35 -0
  68. data/test/tests/controllers_test.rb +49 -0
  69. data/test/tests/eval_environment_test.rb +136 -0
  70. data/test/tests/evel_helpers_test.rb +60 -0
  71. data/test/tests/examples_test.rb +11 -0
  72. data/test/tests/helpers_test.rb +97 -0
  73. data/test/tests/param_set_test.rb +44 -0
  74. data/test/tests/rack_middleware_test.rb +131 -0
  75. data/test/tests/request_test.rb +232 -0
  76. data/test/tests/structures_param_extensions_test.rb +159 -0
  77. data/test/tests/structures_test.rb +398 -0
  78. metadata +71 -56
@@ -0,0 +1,44 @@
1
+ require 'ostruct'
2
+
3
+ class ParamSetTest < Test::Unit::TestCase
4
+
5
+ def test_param_set
6
+ set = Moonrope::ParamSet.new('fruit' => 'Banana')
7
+ # Test that values which aren't included are nil
8
+ assert_equal nil, set.vegetable
9
+ assert_equal nil, set[:vegetable]
10
+ # Test values can be accessed if they are provided
11
+ assert_equal 'Banana', set.fruit
12
+ assert_equal 'Banana', set[:fruit]
13
+ assert_equal 'Banana', set['fruit']
14
+ end
15
+
16
+ def test_default_params
17
+ set = Moonrope::ParamSet.new('fruit' => 'Banana')
18
+ set._defaults = {'vegetable' => 'Tomato', 'fruit' => 'Apple'}
19
+ # Check that the default is provided
20
+ assert_equal 'Tomato', set.vegetable
21
+ # Check that the fruit default isn't used.
22
+ assert_equal 'Banana', set.fruit
23
+ end
24
+
25
+ def test_nilification
26
+ set = Moonrope::ParamSet.new('fruit' => '')
27
+ assert_equal nil, set.fruit
28
+ assert_equal nil, set[:fruit]
29
+ assert_equal nil, set['fruit']
30
+ end
31
+
32
+ def test_key_presence
33
+ set = Moonrope::ParamSet.new('fruit' => 'Apple')
34
+ set._defaults = {'meat' => 'Beef'}
35
+ assert_equal true, set.has?(:fruit)
36
+ assert_equal true, set.has?(:meat)
37
+ assert_equal false, set.has?(:vegetable)
38
+ end
39
+
40
+ class ParamSetCopyTestThing
41
+ attr_accessor :fruit, :vegetable
42
+ end
43
+
44
+ end
@@ -0,0 +1,131 @@
1
+ class RackMiddlewareTest < Test::Unit::TestCase
2
+
3
+ include Rack::Test::Methods
4
+
5
+ def app
6
+ @app ||= begin
7
+ base = Moonrope::Base.new do
8
+ authenticator :default do
9
+ error "Denied", "No suitable credentials were provided."
10
+ lookup do
11
+ # if there is a x-moonrope-username header, check the auth
12
+ # or raise access denied.
13
+ if request.headers['X-Moonrope-Username']
14
+ if request.headers['X-Moonrope-Username'] == 'user' && request.headers['X-Moonrope-Password'] == 'password'
15
+ User.new(:admin => true)
16
+ else
17
+ error "Denied"
18
+ end
19
+ end
20
+ end
21
+ end
22
+ controller :users do
23
+ action :list do
24
+ # return an empty array
25
+ action { [] }
26
+ end
27
+
28
+ action :echo do
29
+ param :name, :required => true
30
+ action { params.name }
31
+ end
32
+ end
33
+ end
34
+ Moonrope::RackMiddleware.new(nil, base)
35
+ end
36
+ end
37
+
38
+ def test_non_api_requests_404
39
+ get "/"
40
+ assert_equal 404, last_response.status
41
+ end
42
+
43
+ def test_api_request_validation
44
+ get "/api/"
45
+ assert_equal 400, last_response.status
46
+ get "/api/v1"
47
+ assert_equal 400, last_response.status
48
+ get "/api/v1/controller"
49
+ assert_equal 400, last_response.status
50
+ end
51
+
52
+ def test_api_methods
53
+ params = {:page => 1}.to_json
54
+ get "/api/v1/users/list", {:params => params}
55
+ assert_equal 200, last_response.status
56
+ assert response_json = JSON.parse(last_response.body)
57
+ assert_equal 'success', response_json['status']
58
+ assert response_json['data'].is_a?(Array)
59
+ assert_equal 'application/json', last_response.headers['Content-Type']
60
+ assert last_response.headers['Content-Length']
61
+ end
62
+
63
+ def test_params_in_body
64
+ post "/api/v1/users/echo", '{"name":"Adam"}', {'CONTENT_TYPE' => 'application/json'}
65
+ assert_equal 200, last_response.status
66
+ assert response_json = JSON.parse(last_response.body)
67
+ assert_equal 'success', response_json['status']
68
+ assert_equal 'Adam', response_json['data']
69
+ end
70
+
71
+ def test_params_in_body_with_charset
72
+ post "/api/v1/users/echo", '{"name":"Adam"}', {'CONTENT_TYPE' => 'application/json; charset=utf8'}
73
+ assert_equal 200, last_response.status
74
+ assert response_json = JSON.parse(last_response.body)
75
+ assert_equal 'success', response_json['status']
76
+ assert_equal 'Adam', response_json['data']
77
+ end
78
+
79
+ def test_passing_invalid_json_renders_a_bad_request
80
+ get "/api/v1/users/list", {:params => "{invalidjson}"}
81
+ assert_equal 400, last_response.status
82
+ assert response_json = JSON.parse(last_response.body)
83
+ assert_equal 'invalid-json', response_json['status']
84
+ end
85
+
86
+ def test_authenticated_api_methods
87
+ # correct credential
88
+ get "/api/v1/users/list", {}, auth_headers('user', 'password')
89
+ assert response_json = JSON.parse(last_response.body)
90
+ assert_equal 'success', response_json['status']
91
+ # invalid password
92
+ get "/api/v1/users/list", {}, auth_headers('user-invalid', 'password-invalid')
93
+ assert response_json = JSON.parse(last_response.body)
94
+ assert_equal 'error', response_json['status']
95
+ assert_equal 'Denied', response_json['data']['code']
96
+ end
97
+
98
+ def test_request_callback_is_invoked
99
+ request_count = 0
100
+ app.base.on_request = Proc.new do |base, env|
101
+ request_count += 1
102
+ end
103
+ assert_equal 0, request_count
104
+ get "/api/v1/users/list"
105
+ assert_equal 1, request_count
106
+ get "/api/v1/users/list"
107
+ assert_equal 2, request_count
108
+ end
109
+
110
+ def test_force_ssl
111
+ begin
112
+ app.base.force_ssl = true
113
+ get "/api/v1/users/list"
114
+ assert_equal 400, last_response.status
115
+ assert response_json = JSON.parse(last_response.body)
116
+ assert_equal 'http-not-supported', response_json['status']
117
+
118
+ get "/api/v1/users/list", {}, {'HTTPS' => 'on'}
119
+ assert_equal 200, last_response.status
120
+ ensure
121
+ app.base.force_ssl = false
122
+ end
123
+ end
124
+
125
+ private
126
+
127
+ def auth_headers(username, password)
128
+ {'HTTP_X_MOONROPE_USERNAME' => username, 'HTTP_X_MOONROPE_PASSWORD' => password}
129
+ end
130
+
131
+ end
@@ -0,0 +1,232 @@
1
+ class RequestTest < Test::Unit::TestCase
2
+
3
+
4
+ def test_validation
5
+ # Create a simple API server with just the users & list controller
6
+ base = Moonrope::Base.new do
7
+ controller :users do
8
+ action :list
9
+ end
10
+ end
11
+
12
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
13
+ assert_equal true, request.valid?
14
+ request = base.request(make_rack_env_hash('/api/v1/missing/unknown'))
15
+ assert_equal false, request.valid?
16
+
17
+ request = base.request(make_rack_env_hash('/api/v1'))
18
+ assert_equal false, request.valid?
19
+ request = base.request(make_rack_env_hash('/api/v1/users'))
20
+ assert_equal false, request.valid?
21
+ end
22
+
23
+ def test_version
24
+ base = Moonrope::Base.new
25
+ request = base.request(make_rack_env_hash('/api/v0/users/list'))
26
+ assert_equal 1, request.version
27
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
28
+ assert_equal 1, request.version
29
+ request = base.request(make_rack_env_hash('/api/v2/users/list'))
30
+ assert_equal 2, request.version
31
+ request = base.request(make_rack_env_hash('/api/v100/users/list'))
32
+ assert_equal 100, request.version
33
+ end
34
+
35
+ def test_controllers_and_actions
36
+ base = Moonrope::Base.new do
37
+ controller :users do
38
+ action :list
39
+ end
40
+ end
41
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
42
+ assert request.controller.is_a?(Moonrope::Controller)
43
+ assert_equal :users, request.controller.name
44
+ assert request.action.is_a?(Moonrope::Action)
45
+ assert_equal :list, request.action.name
46
+ end
47
+
48
+ def test_params_are_accessible
49
+ env = make_rack_env_hash('/api/v1/users/list', {'params' => {'page' => 1}})
50
+ request = Moonrope::Base.new.request(env)
51
+ assert request.params.is_a?(Moonrope::ParamSet)
52
+ assert_equal '1', request.params.page
53
+ end
54
+
55
+ def test_actions_can_be_executed
56
+ base = Moonrope::Base.new do
57
+ controller :users do
58
+ action :list do
59
+ action { true }
60
+ end
61
+ end
62
+ end
63
+
64
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
65
+ assert result = request.execute
66
+ assert result.is_a?(Moonrope::ActionResult), "request.action does not return an ActionResult, was a #{result.class}"
67
+ end
68
+
69
+ def test_headers_are_accessible
70
+ base = Moonrope::Base.new
71
+ env = make_rack_env_hash('/api/v1/users/list', {}, {'HTTP_X_EXAMPLE_HEADER' => 'Hello'})
72
+ request = base.request(env)
73
+ assert_equal 'Hello', request.headers['X-Example-Header']
74
+ end
75
+
76
+ def test_ip_is_accessible
77
+ base = Moonrope::Base.new
78
+ env = make_rack_env_hash('/api/v1/users/list')
79
+ request = base.request(env)
80
+ assert_equal '127.0.0.1', request.ip
81
+ end
82
+
83
+ def test_authenticated_requests
84
+ base = Moonrope::Base.new do
85
+ authenticator :default do
86
+ lookup do
87
+ User.new(:admin => true)
88
+ end
89
+ end
90
+ controller :users do
91
+ action :list do
92
+ action { true }
93
+ end
94
+ end
95
+ end
96
+ # authenticated
97
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
98
+ assert result = request.execute
99
+ assert_equal User, request.identity.class
100
+ assert_equal false, request.anonymous?
101
+ assert_equal true, request.authenticated?
102
+ end
103
+
104
+ def test_authentication_failures
105
+ base = Moonrope::Base.new do
106
+ authenticator :default do
107
+ lookup do
108
+ error :access_denied, "Not permitted"
109
+ end
110
+ end
111
+
112
+ controller :users do
113
+ action :list do
114
+ action { true}
115
+ end
116
+ end
117
+ end
118
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
119
+ assert result = request.execute
120
+ assert_equal "access-denied", result.status
121
+ assert_equal nil, request.identity
122
+ assert_equal true, request.anonymous?
123
+ assert_equal false, request.authenticated?
124
+ end
125
+
126
+ def test_requests_which_authenticator_says_are_anonymous
127
+ base = Moonrope::Base.new do
128
+ authenticator :default do
129
+ lookup { nil }
130
+ end
131
+ controller :users do
132
+ action :list do
133
+ action { true }
134
+ end
135
+ end
136
+ end
137
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
138
+ assert result = request.execute
139
+ assert_equal "success", result.status
140
+ assert_equal nil, request.identity
141
+ assert_equal true, request.anonymous?
142
+ assert_equal false, request.authenticated?
143
+ end
144
+
145
+ def test_trying_to_use_invalid_authenticator_raises_error
146
+ base = Moonrope::Base.new do
147
+ authenticator :default do
148
+ lookup do
149
+ User.new(:admin => true)
150
+ end
151
+ end
152
+ controller :users do
153
+ action :list do
154
+ authenticator :blah
155
+ action { true }
156
+ end
157
+ end
158
+ end
159
+
160
+ request = base.request(make_rack_env_hash('/api/v1/users/list'))
161
+ assert_raises Moonrope::Errors::MissingAuthenticator do
162
+ request.execute
163
+ end
164
+ end
165
+
166
+ def test_raising_errors_from_the_authenticator_lookup
167
+ base = Moonrope::Base.new do
168
+ authenticator :default do
169
+ error 'InvalidToken', 'Token provided is invalid', :attributes => {:token => 'The token looked up'}
170
+ lookup do
171
+ error 'InvalidToken', :token => request.headers['X-Example-Header']
172
+ end
173
+ end
174
+ controller :users do
175
+ action :list do
176
+ action { true }
177
+ end
178
+ end
179
+ end
180
+ request = base.request(make_rack_env_hash('/api/v1/users/list', {}, {"HTTP_X_EXAMPLE_HEADER" => "1234567"}))
181
+ assert result = request.execute
182
+ assert_equal "error", result.status
183
+ assert_equal "InvalidToken", result.data[:code]
184
+ assert_equal "1234567", result.data[:token]
185
+ assert_equal "Token provided is invalid", result.data[:message]
186
+ end
187
+
188
+ def test_appropriate_error_is_returned_from_access_checks
189
+ base = Moonrope::Base.new do
190
+ authenticator :default do
191
+ lookup { :admin }
192
+ rule :default, "CustomError", "Must be authenticated as admin user" do
193
+ identity == :anonymous
194
+ end
195
+ end
196
+ controller :users do
197
+ action :list do
198
+ action { true }
199
+ end
200
+ end
201
+ end
202
+ request = base.request(make_rack_env_hash('/api/v1/users/list', {}, {"HTTP_X_EXAMPLE_HEADER" => "1234567"}))
203
+ assert result = request.execute
204
+ assert_equal "error", result.status
205
+ assert_equal "CustomError", result.data[:code]
206
+ assert_equal "Must be authenticated as admin user", result.data[:message]
207
+ end
208
+
209
+ def test_appropriate_error_can_be_returned_from_authenticator_error_hash
210
+ base = Moonrope::Base.new do
211
+ authenticator :default do
212
+ lookup { :admin }
213
+ error "CustomError", "Some custom error message override"
214
+ rule :default, "CustomError", "Must be authenticated as admin user" do
215
+ identity == :anonymous
216
+ end
217
+ end
218
+ controller :users do
219
+ action :list do
220
+ action { true }
221
+ end
222
+ end
223
+ end
224
+ request = base.request(make_rack_env_hash('/api/v1/users/list', {}, {"HTTP_X_EXAMPLE_HEADER" => "1234567"}))
225
+ assert result = request.execute
226
+ assert_equal "error", result.status
227
+ assert_equal "CustomError", result.data[:code]
228
+ assert_equal "Some custom error message override", result.data[:message]
229
+ end
230
+
231
+
232
+ end
@@ -0,0 +1,159 @@
1
+ class StructuresParamExtensionsTest < Test::Unit::TestCase
2
+ def setup
3
+ @base = Moonrope::Base.new do
4
+ structure :animal do
5
+ basic :id
6
+ full :color
7
+ expansion :user, :structure => :user
8
+ end
9
+ structure :user do
10
+ basic :id
11
+ end
12
+ controller :users do
13
+ action :info do
14
+ action do
15
+ structure @auth_user
16
+ end
17
+ end
18
+ end
19
+ end
20
+ @user = User.new(:id => 456)
21
+ @animal = Animal.new(:id => 123, :user => @user, :color => 'blue')
22
+ end
23
+
24
+ def test_no_expansions_occur_by_default_with_array
25
+ request = FakeRequest.new(:params => {'_expansions' => ['user']})
26
+ environment = Moonrope::EvalEnvironment.new(@base, request)
27
+ structure = environment.structure(:animal, @animal)
28
+ assert_equal nil, structure[:user]
29
+ end
30
+
31
+ def test_default_behaviour_when_paramable_is_only_option
32
+ request = FakeRequest.new(:params => {})
33
+ environment = Moonrope::EvalEnvironment.new(@base, request)
34
+ # From nil
35
+ structure = environment.structure(:animal, @animal, :paramable => true)
36
+ assert_equal nil, structure[:user]
37
+ assert_equal nil, structure[:color]
38
+ end
39
+
40
+ def test_no_expansions_occur_by_default_with_true
41
+ request = FakeRequest.new(:params => {'_expansions' => true})
42
+ environment = Moonrope::EvalEnvironment.new(@base, request)
43
+ structure = environment.structure(:animal, @animal)
44
+ assert_equal nil, structure[:user]
45
+ end
46
+
47
+ def test_expansions_use_paramable_value_as_default
48
+ request = FakeRequest.new(:params => {})
49
+ environment = Moonrope::EvalEnvironment.new(@base, request)
50
+ # From nil
51
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => nil})
52
+ assert_equal nil, structure[:user]
53
+ # From true
54
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => true})
55
+ assert_equal Hash, structure[:user].class
56
+ # From a list
57
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => [:user]})
58
+ assert_equal Hash, structure[:user].class
59
+ end
60
+
61
+ def test_all_expansions_are_provided_when_paramable_is_true
62
+ request = FakeRequest.new(:params => {"_expansions" => true})
63
+ environment = Moonrope::EvalEnvironment.new(@base, request)
64
+ structure = environment.structure(:animal, @animal, :paramable => true)
65
+ assert_equal Hash, structure[:user].class
66
+ end
67
+
68
+ def test_using_array_as_expansions_param
69
+ request = FakeRequest.new(:params => {'_expansions' => ['user']})
70
+ environment = Moonrope::EvalEnvironment.new(@base, request)
71
+ # Works
72
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => [:user]})
73
+ assert_equal Hash, structure[:user].class
74
+ # Works
75
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => true})
76
+ assert_equal Hash, structure[:user].class
77
+ # Shouldn't ret
78
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => [:other]})
79
+ assert_equal nil, structure[:user]
80
+ end
81
+
82
+ def test_surpressing_default_expansions_with_empty_array
83
+ request = FakeRequest.new(:params => {'_expansions' => []})
84
+ environment = Moonrope::EvalEnvironment.new(@base, request)
85
+ # Shouldn't return the user structure because we've asked for none
86
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => [:user]})
87
+ assert_equal nil, structure[:user]
88
+ # Shouldn't return the user structure because we've asked for none
89
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => true})
90
+ assert_equal nil, structure[:user]
91
+ end
92
+
93
+ def test_surpressing_default_expansions_with_false
94
+ request = FakeRequest.new(:params => {'_expansions' => false})
95
+ environment = Moonrope::EvalEnvironment.new(@base, request)
96
+ # Shouldn't return the user structure because we've asked for none
97
+ structure = environment.structure(:animal, @animal, :paramable => true)
98
+ assert_equal nil, structure[:user]
99
+ # Shouldn't return the user structure because we've asked for none
100
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => [:user]})
101
+ assert_equal nil, structure[:user]
102
+ # Shouldn't return the user structure because we've asked for none
103
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => true})
104
+ assert_equal nil, structure[:user]
105
+ end
106
+
107
+
108
+ def test_using_true_as_expansions_param_to_return_all_suitable_expansions
109
+ request = FakeRequest.new(:params => {'_expansions' => true})
110
+ environment = Moonrope::EvalEnvironment.new(@base, request)
111
+ # Requesting all with no default
112
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => nil})
113
+ assert_equal Hash, structure[:user].class
114
+ # Requesting all with no array default
115
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => [:user]})
116
+ assert_equal Hash, structure[:user].class
117
+ # Requesting all with true default
118
+ structure = environment.structure(:animal, @animal, :paramable => {:expansions => true})
119
+ assert_equal Hash, structure[:user].class
120
+ end
121
+
122
+ def test_empty_paramable_array
123
+ request = FakeRequest.new(:params => {'_expansions' => true})
124
+ environment = Moonrope::EvalEnvironment.new(@base, request)
125
+ # Should not return anything because paramable doesn't specify expansions
126
+ # as a suitable option
127
+ structure = environment.structure(:animal, @animal, :paramable => {})
128
+ assert_equal nil, structure[:user]
129
+ end
130
+
131
+ def test_returning_full_data_by_default
132
+ request = FakeRequest.new()
133
+ environment = Moonrope::EvalEnvironment.new(@base, request)
134
+ structure = environment.structure(:animal, @animal, :paramable => {:full => true, :expansions => false})
135
+ assert_equal String, structure[:color].class
136
+ end
137
+
138
+ def test_full_value_provides_full_access
139
+ request = FakeRequest.new(:params => {'_full' => true})
140
+ environment = Moonrope::EvalEnvironment.new(@base, request)
141
+ # No full value set
142
+ structure = environment.structure(:animal, @animal, :paramable => {})
143
+ assert_equal nil, structure[:color]
144
+ # With full set as default
145
+ structure = environment.structure(:animal, @animal, :paramable => {:full => true})
146
+ assert_equal String, structure[:color].class
147
+ # With full set as hidden by default
148
+ structure = environment.structure(:animal, @animal, :paramable => {:full => false})
149
+ assert_equal String, structure[:color].class
150
+ end
151
+
152
+ def test_supressing_default_full_data
153
+ request = FakeRequest.new(:params => {'_full' => false})
154
+ environment = Moonrope::EvalEnvironment.new(@base, request)
155
+ structure = environment.structure(:animal, @animal, :paramable => {:full => true})
156
+ assert_equal nil, structure[:color]
157
+ end
158
+
159
+ end