sinatra_resource 0.1.0

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 (75) hide show
  1. data/.document +5 -0
  2. data/.gitignore +7 -0
  3. data/LICENSE +20 -0
  4. data/README.mdown +28 -0
  5. data/Rakefile +34 -0
  6. data/VERSION +1 -0
  7. data/examples/datacatalog/Rakefile +23 -0
  8. data/examples/datacatalog/app.rb +15 -0
  9. data/examples/datacatalog/config/config.rb +66 -0
  10. data/examples/datacatalog/config/config.yml +11 -0
  11. data/examples/datacatalog/config.ru +6 -0
  12. data/examples/datacatalog/lib/base.rb +9 -0
  13. data/examples/datacatalog/lib/resource.rb +73 -0
  14. data/examples/datacatalog/lib/roles.rb +15 -0
  15. data/examples/datacatalog/models/categorization.rb +31 -0
  16. data/examples/datacatalog/models/category.rb +28 -0
  17. data/examples/datacatalog/models/source.rb +33 -0
  18. data/examples/datacatalog/models/user.rb +51 -0
  19. data/examples/datacatalog/resources/categories.rb +32 -0
  20. data/examples/datacatalog/resources/sources.rb +35 -0
  21. data/examples/datacatalog/resources/users.rb +26 -0
  22. data/examples/datacatalog/tasks/db.rake +29 -0
  23. data/examples/datacatalog/tasks/test.rake +16 -0
  24. data/examples/datacatalog/test/helpers/assertions/assert_include.rb +17 -0
  25. data/examples/datacatalog/test/helpers/assertions/assert_not_include.rb +17 -0
  26. data/examples/datacatalog/test/helpers/lib/model_factories.rb +49 -0
  27. data/examples/datacatalog/test/helpers/lib/model_helpers.rb +30 -0
  28. data/examples/datacatalog/test/helpers/lib/request_helpers.rb +53 -0
  29. data/examples/datacatalog/test/helpers/model_test_helper.rb +5 -0
  30. data/examples/datacatalog/test/helpers/resource_test_helper.rb +5 -0
  31. data/examples/datacatalog/test/helpers/shared/api_keys.rb +48 -0
  32. data/examples/datacatalog/test/helpers/shared/common_body_responses.rb +15 -0
  33. data/examples/datacatalog/test/helpers/shared/status_codes.rb +61 -0
  34. data/examples/datacatalog/test/helpers/test_cases/model_test_case.rb +6 -0
  35. data/examples/datacatalog/test/helpers/test_cases/resource_test_case.rb +36 -0
  36. data/examples/datacatalog/test/helpers/test_helper.rb +36 -0
  37. data/examples/datacatalog/test/models/categorization_test.rb +40 -0
  38. data/examples/datacatalog/test/models/category_test.rb +35 -0
  39. data/examples/datacatalog/test/models/source_test.rb +37 -0
  40. data/examples/datacatalog/test/models/user_test.rb +77 -0
  41. data/examples/datacatalog/test/resources/categories/categories_delete_test.rb +112 -0
  42. data/examples/datacatalog/test/resources/categories/categories_get_many_test.rb +58 -0
  43. data/examples/datacatalog/test/resources/categories/categories_get_one_test.rb +75 -0
  44. data/examples/datacatalog/test/resources/categories/categories_post_test.rb +135 -0
  45. data/examples/datacatalog/test/resources/categories/categories_put_test.rb +140 -0
  46. data/examples/datacatalog/test/resources/sources/sources_delete_test.rb +112 -0
  47. data/examples/datacatalog/test/resources/sources/sources_get_many_test.rb +58 -0
  48. data/examples/datacatalog/test/resources/sources/sources_get_one_test.rb +74 -0
  49. data/examples/datacatalog/test/resources/sources/sources_post_test.rb +184 -0
  50. data/examples/datacatalog/test/resources/sources/sources_put_test.rb +227 -0
  51. data/examples/datacatalog/test/resources/users/users_delete_test.rb +134 -0
  52. data/examples/datacatalog/test/resources/users/users_get_many_test.rb +111 -0
  53. data/examples/datacatalog/test/resources/users/users_get_one_test.rb +75 -0
  54. data/examples/datacatalog/test/resources/users/users_post_test.rb +142 -0
  55. data/examples/datacatalog/test/resources/users/users_put_test.rb +171 -0
  56. data/lib/builder/helpers.rb +319 -0
  57. data/lib/builder/mongo_helpers.rb +70 -0
  58. data/lib/builder.rb +84 -0
  59. data/lib/exceptions.rb +10 -0
  60. data/lib/resource.rb +171 -0
  61. data/lib/roles.rb +163 -0
  62. data/lib/sinatra_resource.rb +6 -0
  63. data/notes/keywords.mdown +1 -0
  64. data/notes/permissions.mdown +181 -0
  65. data/notes/questions.mdown +18 -0
  66. data/notes/see_also.mdown +3 -0
  67. data/notes/synonyms.mdown +7 -0
  68. data/notes/to_do.mdown +7 -0
  69. data/notes/uniform_interface.mdown +22 -0
  70. data/sinatra_resource.gemspec +183 -0
  71. data/spec/sinatra_resource_spec.rb +7 -0
  72. data/spec/spec_helper.rb +9 -0
  73. data/tasks/spec.rake +13 -0
  74. data/tasks/yard.rake +13 -0
  75. metadata +253 -0
@@ -0,0 +1,184 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class SourcesPostResourceTest < ResourceTestCase
4
+
5
+ include DataCatalog
6
+
7
+ def app; Sources end
8
+
9
+ before do
10
+ @source_count = Source.all.length
11
+ @valid_params = {
12
+ :title => "New Source",
13
+ :url => "http://data.gov/details/123"
14
+ }
15
+ @extra_admin_params = { :raw => { "key" => "value" } }
16
+ end
17
+
18
+ shared "no new sources" do
19
+ test "should not change number of source documents in database" do
20
+ assert_equal @source_count, Source.all.length
21
+ end
22
+ end
23
+
24
+ shared "one new source" do
25
+ test "should add one source document to database" do
26
+ assert_equal @source_count + 1, Source.all.length
27
+ end
28
+ end
29
+
30
+ shared "correct Location header" do
31
+ test "should set Location header correctly" do
32
+ base_uri = Config.environment_config["base_uri"]
33
+ path = %(/sources/#{parsed_response_body["id"]})
34
+ expected = URI.join(base_uri, path).to_s
35
+ assert_equal expected, last_response.headers['Location']
36
+ end
37
+ end
38
+
39
+ context "post /" do
40
+ context "anonymous" do
41
+ before do
42
+ post "/", @valid_params
43
+ end
44
+
45
+ use "return 401 because the API key is missing"
46
+ use "no new sources"
47
+ end
48
+
49
+ context "incorrect API key" do
50
+ before do
51
+ post "/", @valid_params.merge(:api_key => BAD_API_KEY)
52
+ end
53
+
54
+ use "return 401 because the API key is invalid"
55
+ use "no new sources"
56
+ end
57
+ end
58
+
59
+ %w(basic).each do |role|
60
+ [:title, :url].each do |missing|
61
+ context "#{role} : post / but missing #{missing}" do
62
+ before do
63
+ post "/", valid_params_for(role).delete_if { |k, v| k == missing }
64
+ end
65
+
66
+ use "return 401 Unauthorized"
67
+ use "no new sources"
68
+ end
69
+ end
70
+
71
+ [:id, :created_at, :updated_at, :categories].each do |invalid|
72
+ context "#{role} : post / but with #{invalid}" do
73
+ before do
74
+ post "/", valid_params_for(role).merge(invalid => 9)
75
+ end
76
+
77
+ use "return 401 Unauthorized"
78
+ use "no new sources"
79
+ end
80
+ end
81
+
82
+ context "#{role} : post / with valid params" do
83
+ before do
84
+ post "/", valid_params_for(role)
85
+ end
86
+
87
+ use "return 401 Unauthorized"
88
+ use "no new sources"
89
+ end
90
+ end
91
+
92
+ %w(curator).each do |role|
93
+ [:title, :url].each do |missing|
94
+ context "#{role} : post / but missing #{missing}" do
95
+ before do
96
+ post "/", valid_params_for(role).delete_if { |k, v| k == missing }
97
+ end
98
+
99
+ use "return 400 Bad Request"
100
+ use "no new sources"
101
+ missing_param missing
102
+ end
103
+ end
104
+
105
+ [:raw, :id, :created_at, :updated_at, :categories].each do |invalid|
106
+ context "#{role} : post / but with #{invalid}" do
107
+ before do
108
+ post "/", valid_params_for(role).merge(invalid => 9)
109
+ end
110
+
111
+ use "return 400 Bad Request"
112
+ use "no new sources"
113
+ invalid_param invalid
114
+ end
115
+ end
116
+
117
+ context "#{role} : post / with valid params" do
118
+ before do
119
+ post "/", valid_params_for(role)
120
+ end
121
+
122
+ use "return 201 Created"
123
+ use "correct Location header"
124
+ use "one new source"
125
+ doc_properties %w(title url raw id created_at updated_at categories)
126
+
127
+ test "should set all fields in database" do
128
+ source = Source.find_by_id(parsed_response_body["id"])
129
+ raise "Cannot find source" unless source
130
+ @valid_params.each_pair do |key, value|
131
+ assert_equal value, source[key]
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ %w(admin).each do |role|
138
+ [:title, :url].each do |missing|
139
+ context "#{role} : post / but missing #{missing}" do
140
+ before do
141
+ post "/", valid_params_for(role).
142
+ merge(@extra_admin_params).delete_if { |k, v| k == missing }
143
+ end
144
+
145
+ use "return 400 Bad Request"
146
+ use "no new sources"
147
+ missing_param missing
148
+ end
149
+ end
150
+
151
+ [:id, :created_at, :updated_at, :categories].each do |invalid|
152
+ context "#{role} : post / but with #{invalid}" do
153
+ before do
154
+ post "/", valid_params_for(role).
155
+ merge(@extra_admin_params).merge(invalid => 9)
156
+ end
157
+
158
+ use "return 400 Bad Request"
159
+ use "no new sources"
160
+ invalid_param invalid
161
+ end
162
+ end
163
+
164
+ context "#{role} : post / with valid params" do
165
+ before do
166
+ post "/", valid_params_for(role).merge(@extra_admin_params)
167
+ end
168
+
169
+ use "return 201 Created"
170
+ use "correct Location header"
171
+ use "one new source"
172
+ doc_properties %w(title url raw id created_at updated_at categories)
173
+
174
+ test "should set all fields in database" do
175
+ source = Source.find_by_id(parsed_response_body["id"])
176
+ raise "Cannot find source" unless source
177
+ @valid_params.merge(@extra_admin_params).each_pair do |key, value|
178
+ assert_equal value, source[key]
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ end
@@ -0,0 +1,227 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class SourcesPutResourceTest < ResourceTestCase
4
+
5
+ include DataCatalog
6
+
7
+ def app; Sources end
8
+
9
+ before do
10
+ @source = create_source
11
+ @source_copy = @source.dup
12
+ @valid_params = {
13
+ :title => "Changed Source",
14
+ :url => "http://updated.com/details/7"
15
+ }
16
+ @extra_admin_params = { :raw => { "key" => "value" } }
17
+ end
18
+
19
+ after do
20
+ @source.destroy
21
+ end
22
+
23
+ shared "source unchanged" do
24
+ test "should not change source in database" do
25
+ assert_equal @source_copy, Source.find_by_id(@source.id)
26
+ end
27
+ end
28
+
29
+ context "put /:id" do
30
+ context "anonymous" do
31
+ before do
32
+ put "/#{@source.id}", @valid_params
33
+ end
34
+
35
+ use "return 401 because the API key is missing"
36
+ use "source unchanged"
37
+ end
38
+
39
+ context "incorrect API key" do
40
+ before do
41
+ put "/#{@source.id}", @valid_params.merge(:api_key => BAD_API_KEY)
42
+ end
43
+
44
+ use "return 401 because the API key is invalid"
45
+ use "source unchanged"
46
+ end
47
+ end
48
+
49
+ %w(basic).each do |role|
50
+ [:id, :created_at, :updated_at, :categories].each do |invalid|
51
+ context "#{role} : put / but with #{invalid}" do
52
+ before do
53
+ put "/#{@source.id}", valid_params_for(role).merge(invalid => 9)
54
+ end
55
+
56
+ use "return 401 Unauthorized"
57
+ use "source unchanged"
58
+ end
59
+ end
60
+
61
+ [:title, :url].each do |erase|
62
+ context "#{role} : put / but blanking out #{erase}" do
63
+ before do
64
+ put "/#{@source.id}", valid_params_for(role).merge(erase => "")
65
+ end
66
+
67
+ use "return 401 Unauthorized"
68
+ use "source unchanged"
69
+ end
70
+ end
71
+
72
+ [:title, :url].each do |missing|
73
+ context "#{role} : put /:id without #{missing}" do
74
+ before do
75
+ put "/#{@source.id}", valid_params_for(role).delete_if { |k, v| k == missing }
76
+ end
77
+
78
+ use "return 401 Unauthorized"
79
+ use "source unchanged"
80
+ end
81
+ end
82
+
83
+ context "#{role} : put /:id with valid params" do
84
+ before do
85
+ put "/#{@source.id}", valid_params_for(role)
86
+ end
87
+
88
+ use "return 401 Unauthorized"
89
+ use "source unchanged"
90
+ end
91
+ end
92
+
93
+ %w(curator).each do |role|
94
+ [:raw, :created_at, :updated_at, :categories].each do |invalid|
95
+ context "#{role} : put / but with #{invalid}" do
96
+ before do
97
+ put "/#{@source.id}", valid_params_for(role).merge(invalid => 9)
98
+ end
99
+
100
+ use "return 400 Bad Request"
101
+ use "source unchanged"
102
+ invalid_param invalid
103
+ end
104
+ end
105
+
106
+ [:title, :url].each do |erase|
107
+ context "#{role} : put / but blanking out #{erase}" do
108
+ before do
109
+ put "/#{@source.id}", valid_params_for(role).merge(erase => "")
110
+ end
111
+
112
+ use "return 400 Bad Request"
113
+ use "source unchanged"
114
+ missing_param erase
115
+ end
116
+ end
117
+
118
+ [:title, :url].each do |missing|
119
+ context "#{role} : put /:id without #{missing}" do
120
+ before do
121
+ put "/#{@source.id}", valid_params_for(role).delete_if { |k, v| k == missing }
122
+ end
123
+
124
+ use "return 200 Ok"
125
+ doc_properties %w(title url raw id created_at updated_at categories)
126
+
127
+ test "should change correct fields in database" do
128
+ source = Source.find_by_id(@source.id)
129
+ @valid_params.each_pair do |key, value|
130
+ assert_equal(value, source[key]) if key != missing
131
+ end
132
+ assert_equal @source_copy[missing], source[missing]
133
+ end
134
+ end
135
+ end
136
+
137
+ context "#{role} : put /:id with valid params" do
138
+ before do
139
+ put "/#{@source.id}", valid_params_for(role)
140
+ end
141
+
142
+ use "return 200 Ok"
143
+ doc_properties %w(title url raw id created_at updated_at categories)
144
+
145
+ test "should change correct fields in database" do
146
+ source = Source.find_by_id(@source.id)
147
+ @valid_params.each_pair do |key, value|
148
+ assert_equal value, source[key]
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ %w(admin).each do |role|
155
+ [:created_at, :updated_at, :categories].each do |invalid|
156
+ context "#{role} : put / but with #{invalid}" do
157
+ before do
158
+ put "/#{@source.id}", valid_params_for(role).
159
+ merge(@extra_admin_params).merge(invalid => 9)
160
+ end
161
+
162
+ use "return 400 Bad Request"
163
+ use "source unchanged"
164
+ invalid_param invalid
165
+ end
166
+ end
167
+
168
+ [:title, :url].each do |erase|
169
+ context "#{role} : put / but blanking out #{erase}" do
170
+ before do
171
+ put "/#{@source.id}", valid_params_for(role).
172
+ merge(@extra_admin_params).merge(erase => "")
173
+ end
174
+
175
+ use "return 400 Bad Request"
176
+ use "source unchanged"
177
+ missing_param erase
178
+ end
179
+ end
180
+
181
+ context "#{role} : put /:id with no parameters" do
182
+ before do
183
+ put "/#{@source.id}", :api_key => api_key_for(role)
184
+ end
185
+
186
+ use "return 400 because no parameters were given"
187
+ use "source unchanged"
188
+ end
189
+
190
+ [:title, :url].each do |missing|
191
+ context "#{role} : put /:id without #{missing}" do
192
+ before do
193
+ put "/#{@source.id}", valid_params_for(role).
194
+ merge(@extra_admin_params).delete_if { |k, v| k == missing }
195
+ end
196
+
197
+ use "return 200 Ok"
198
+ doc_properties %w(title url raw id created_at updated_at categories)
199
+
200
+ test "should change correct fields in database" do
201
+ source = Source.find_by_id(@source.id)
202
+ @valid_params.merge(@extra_admin_params).each_pair do |key, value|
203
+ assert_equal(value, source[key]) if key != missing
204
+ end
205
+ assert_equal @source_copy[missing], source[missing]
206
+ end
207
+ end
208
+ end
209
+
210
+ context "#{role} : put /:id with valid params" do
211
+ before do
212
+ put "/#{@source.id}", valid_params_for(role).merge(@extra_admin_params)
213
+ end
214
+
215
+ use "return 200 Ok"
216
+ doc_properties %w(title url raw id created_at updated_at categories)
217
+
218
+ test "should change all fields in database" do
219
+ source = Source.find_by_id(@source.id)
220
+ @valid_params.merge(@extra_admin_params).each_pair do |key, value|
221
+ assert_equal value, source[key]
222
+ end
223
+ end
224
+ end
225
+ end
226
+
227
+ end
@@ -0,0 +1,134 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class UsersDeleteResourceTest < ResourceTestCase
4
+
5
+ include DataCatalog
6
+
7
+ def app; Users end
8
+
9
+ before do
10
+ @user = create_user
11
+ @user_count = User.all.length
12
+ end
13
+
14
+ after do
15
+ @user.destroy
16
+ end
17
+
18
+ shared "no change in user count" do
19
+ test "should not change number of user documents in database" do
20
+ assert_equal @user_count, User.all.length
21
+ end
22
+ end
23
+
24
+ shared "one less user" do
25
+ test "should remove one user document from database" do
26
+ assert_equal @user_count - 1, User.all.length
27
+ end
28
+ end
29
+
30
+ context "delete /:id" do
31
+ context "anonymous" do
32
+ before do
33
+ delete "/#{@user.id}"
34
+ end
35
+
36
+ use "return 401 because the API key is missing"
37
+ use "no change in user count"
38
+ end
39
+
40
+ context "incorrect API key" do
41
+ before do
42
+ delete "/#{@user.id}", :api_key => BAD_API_KEY
43
+ end
44
+
45
+ use "return 401 because the API key is invalid"
46
+ use "no change in user count"
47
+ end
48
+ end
49
+
50
+ %w(basic curator).each do |role|
51
+ context "#{role} : delete /:fake_id" do
52
+ before do
53
+ delete "/#{FAKE_ID}", :api_key => api_key_for(role)
54
+ end
55
+
56
+ use "return 401 Unauthorized"
57
+ use "no change in user count"
58
+ end
59
+
60
+ context "#{role} : delete /:id" do
61
+ before do
62
+ delete "/#{@user.id}",
63
+ :api_key => api_key_for(role),
64
+ :key => "value"
65
+ end
66
+
67
+ use "return 401 Unauthorized"
68
+ use "no change in user count"
69
+ end
70
+
71
+ context "#{role} : delete /:id" do
72
+ before do
73
+ delete "/#{@user.id}", :api_key => api_key_for(role)
74
+ end
75
+
76
+ use "return 401 Unauthorized"
77
+ use "no change in user count"
78
+ end
79
+ end
80
+
81
+ context "owner" do
82
+ context "delete /:id" do
83
+ before do
84
+ delete "/#{@user.id}",
85
+ :api_key => @user._api_key,
86
+ :key => "value"
87
+ end
88
+
89
+ use "return 400 because parameters were not empty"
90
+ use "no change in user count"
91
+ end
92
+
93
+ context "delete /:id" do
94
+ before do
95
+ delete "/#{@user.id}", :api_key => @user._api_key
96
+ end
97
+
98
+ use "return 204 No Content"
99
+ use "one less user"
100
+ end
101
+ end
102
+
103
+ %(admin).each do |role|
104
+ context "#{role} : delete /:fake_id" do
105
+ before do
106
+ delete "/#{FAKE_ID}", :api_key => api_key_for(role)
107
+ end
108
+
109
+ use "return 404 Not Found"
110
+ use "no change in user count"
111
+ end
112
+
113
+ context "#{role} : delete /:id" do
114
+ before do
115
+ delete "/#{@user.id}",
116
+ :api_key => api_key_for(role),
117
+ :key => "value"
118
+ end
119
+
120
+ use "return 400 because parameters were not empty"
121
+ use "no change in user count"
122
+ end
123
+
124
+ context "#{role} : delete /:id" do
125
+ before do
126
+ delete "/#{@user.id}", :api_key => api_key_for(role)
127
+ end
128
+
129
+ use "return 204 No Content"
130
+ use "one less user"
131
+ end
132
+ end
133
+
134
+ end
@@ -0,0 +1,111 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../helpers/resource_test_helper')
2
+
3
+ class UsersGetManyResourceTest < ResourceTestCase
4
+
5
+ def app; DataCatalog::Users end
6
+
7
+ before do
8
+ @users = 3.times.map do |i|
9
+ create_user(
10
+ :name => "User #{i}",
11
+ :email => "user-#{i}@inter.net"
12
+ )
13
+ end
14
+ end
15
+
16
+ after do
17
+ @users.each { |x| x.destroy }
18
+ end
19
+
20
+ NAMES = [
21
+ "admin User",
22
+ "basic User",
23
+ "curator User",
24
+ "User 0",
25
+ "User 1",
26
+ "User 2"
27
+ ].sort
28
+
29
+ EMAILS = %w(
30
+ admin-user@inter.net
31
+ basic-user@inter.net
32
+ curator-user@inter.net
33
+ user-0@inter.net
34
+ user-1@inter.net
35
+ user-2@inter.net
36
+ ).sort
37
+
38
+ context "get /" do
39
+ context "anonymous" do
40
+ before do
41
+ get "/"
42
+ end
43
+
44
+ use "return 401 because the API key is missing"
45
+ end
46
+
47
+ context "incorrect API key" do
48
+ before do
49
+ get "/", :api_key => BAD_API_KEY
50
+ end
51
+
52
+ use "return 401 because the API key is invalid"
53
+ end
54
+ end
55
+
56
+ %w(basic curator).each do |role|
57
+ context "#{role} : get /" do
58
+ before do
59
+ get "/", :api_key => api_key_for(role)
60
+ end
61
+
62
+ use "return 200 Ok"
63
+
64
+ test "body should have 6 users" do
65
+ assert_equal 6, parsed_response_body.length
66
+ end
67
+
68
+ test "body should have correct names" do
69
+ actual = parsed_response_body.map { |e| e["name"] }
70
+ assert_equal NAMES, actual.sort
71
+ end
72
+
73
+ test "body elements should be correct" do
74
+ parsed_response_body.each do |element|
75
+ if element["id"] == user_for(role).id
76
+ assert_properties(%w(name email role _api_key id created_at updated_at), element)
77
+ else
78
+ assert_properties(%w(name id created_at updated_at), element)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ %w(admin).each do |role|
86
+ context "#{role} : get /" do
87
+ before do
88
+ get "/", :api_key => api_key_for(role)
89
+ end
90
+
91
+ use "return 200 Ok"
92
+
93
+ test "body should have 6 users" do
94
+ assert_equal 6, parsed_response_body.length
95
+ end
96
+
97
+ test "body should have correct names" do
98
+ actual = parsed_response_body.map { |e| e["name"] }
99
+ assert_equal NAMES, actual.sort
100
+ end
101
+
102
+ test "body should have correct emails" do
103
+ actual = parsed_response_body.map { |e| e["email"] }
104
+ assert_equal EMAILS, actual.sort
105
+ end
106
+
107
+ docs_properties %w(name email role _api_key id created_at updated_at)
108
+ end
109
+ end
110
+
111
+ end