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.
- checksums.yaml +5 -5
- data/Gemfile +9 -0
- data/Gemfile.lock +47 -0
- data/MIT-LICENCE +20 -0
- data/README.md +24 -0
- data/bin/moonrope +28 -0
- data/docs/authentication.md +114 -0
- data/docs/controllers.md +106 -0
- data/docs/exceptions.md +27 -0
- data/docs/introduction.md +29 -0
- data/docs/structures.md +214 -0
- data/example/authentication.rb +50 -0
- data/example/controllers/meta_controller.rb +14 -0
- data/example/controllers/users_controller.rb +92 -0
- data/example/structures/pet_structure.rb +12 -0
- data/example/structures/user_structure.rb +35 -0
- data/lib/moonrope.rb +5 -4
- data/lib/moonrope/action.rb +170 -40
- data/lib/moonrope/authenticator.rb +42 -0
- data/lib/moonrope/base.rb +67 -6
- data/lib/moonrope/controller.rb +4 -2
- data/lib/moonrope/doc_context.rb +94 -0
- data/lib/moonrope/doc_server.rb +123 -0
- data/lib/moonrope/dsl/action_dsl.rb +159 -9
- data/lib/moonrope/dsl/authenticator_dsl.rb +35 -0
- data/lib/moonrope/dsl/base_dsl.rb +21 -18
- data/lib/moonrope/dsl/controller_dsl.rb +60 -9
- data/lib/moonrope/dsl/filterable_dsl.rb +27 -0
- data/lib/moonrope/dsl/structure_dsl.rb +28 -2
- data/lib/moonrope/errors.rb +13 -0
- data/lib/moonrope/eval_environment.rb +82 -3
- data/lib/moonrope/eval_helpers.rb +47 -8
- data/lib/moonrope/eval_helpers/filter_helper.rb +82 -0
- data/lib/moonrope/guard.rb +35 -0
- data/lib/moonrope/html_generator.rb +65 -0
- data/lib/moonrope/param_set.rb +11 -1
- data/lib/moonrope/rack_middleware.rb +66 -37
- data/lib/moonrope/railtie.rb +31 -14
- data/lib/moonrope/request.rb +43 -15
- data/lib/moonrope/structure.rb +100 -18
- data/lib/moonrope/structure_attribute.rb +39 -0
- data/lib/moonrope/version.rb +1 -1
- data/moonrope.gemspec +21 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/specs/action_spec.rb +455 -0
- data/spec/specs/base_spec.rb +29 -0
- data/spec/specs/controller_spec.rb +31 -0
- data/spec/specs/param_set_spec.rb +31 -0
- data/templates/basic/_action_form.erb +77 -0
- data/templates/basic/_errors_table.erb +32 -0
- data/templates/basic/_structure_attributes_list.erb +55 -0
- data/templates/basic/action.erb +168 -0
- data/templates/basic/assets/lock.svg +3 -0
- data/templates/basic/assets/reset.css +101 -0
- data/templates/basic/assets/style.css +348 -0
- data/templates/basic/assets/tool.svg +4 -0
- data/templates/basic/assets/try.js +157 -0
- data/templates/basic/authenticator.erb +52 -0
- data/templates/basic/controller.erb +20 -0
- data/templates/basic/index.erb +114 -0
- data/templates/basic/layout.erb +46 -0
- data/templates/basic/structure.erb +23 -0
- data/test/test_helper.rb +81 -0
- data/test/tests/action_access_test.rb +63 -0
- data/test/tests/actions_test.rb +524 -0
- data/test/tests/authenticators_test.rb +87 -0
- data/test/tests/base_test.rb +35 -0
- data/test/tests/controllers_test.rb +49 -0
- data/test/tests/eval_environment_test.rb +136 -0
- data/test/tests/evel_helpers_test.rb +60 -0
- data/test/tests/examples_test.rb +11 -0
- data/test/tests/helpers_test.rb +97 -0
- data/test/tests/param_set_test.rb +44 -0
- data/test/tests/rack_middleware_test.rb +131 -0
- data/test/tests/request_test.rb +232 -0
- data/test/tests/structures_param_extensions_test.rb +159 -0
- data/test/tests/structures_test.rb +398 -0
- 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
|