moonrope 1.3.3 → 2.0.2

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