rabl 0.3.0 → 0.5.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 (146) hide show
  1. data/.gitignore +2 -0
  2. data/.travis.yml +10 -0
  3. data/CHANGELOG.md +34 -0
  4. data/Gemfile +14 -1
  5. data/README.md +53 -4
  6. data/Rakefile +26 -1
  7. data/fixtures/ashared/NOTES +35 -0
  8. data/fixtures/ashared/README +35 -0
  9. data/fixtures/ashared/migrate/20111002092016_create_users.rb +15 -0
  10. data/fixtures/ashared/migrate/20111002092019_create_posts.rb +14 -0
  11. data/fixtures/ashared/migrate/20111002092024_create_phone_numbers.rb +16 -0
  12. data/fixtures/ashared/models/phone_number.rb +7 -0
  13. data/fixtures/ashared/models/post.rb +3 -0
  14. data/fixtures/ashared/models/user.rb +3 -0
  15. data/fixtures/ashared/views/layouts/application.html.erb +6 -0
  16. data/fixtures/ashared/views/posts/date.json.rabl +3 -0
  17. data/fixtures/ashared/views/posts/index.json.rabl +11 -0
  18. data/fixtures/ashared/views/posts/show.json.rabl +16 -0
  19. data/fixtures/ashared/views/users/index.rabl +3 -0
  20. data/fixtures/ashared/views/users/phone_number.rabl +6 -0
  21. data/fixtures/ashared/views/users/show.rabl +16 -0
  22. data/fixtures/padrino_test/.components +7 -0
  23. data/fixtures/padrino_test/.gitignore +7 -0
  24. data/fixtures/padrino_test/Gemfile +17 -0
  25. data/fixtures/padrino_test/Rakefile +3 -0
  26. data/fixtures/padrino_test/app/app.rb +59 -0
  27. data/fixtures/padrino_test/app/controllers/posts.rb +11 -0
  28. data/fixtures/padrino_test/app/controllers/users.rb +11 -0
  29. data/fixtures/padrino_test/app/helpers/posts_helper.rb +7 -0
  30. data/fixtures/padrino_test/app/helpers/users_helper.rb +7 -0
  31. data/fixtures/padrino_test/config.ru +9 -0
  32. data/fixtures/padrino_test/config/apps.rb +34 -0
  33. data/fixtures/padrino_test/config/boot.rb +29 -0
  34. data/fixtures/padrino_test/config/database.rb +43 -0
  35. data/fixtures/padrino_test/db/schema.rb +42 -0
  36. data/fixtures/padrino_test/public/favicon.ico +0 -0
  37. data/fixtures/padrino_test/test/app/controllers/posts_controller_test.rb +108 -0
  38. data/fixtures/padrino_test/test/app/controllers/users_controller_test.rb +87 -0
  39. data/fixtures/padrino_test/test/test.rake +18 -0
  40. data/fixtures/padrino_test/test/test_config.rb +18 -0
  41. data/fixtures/rails2/.gitignore +1 -0
  42. data/fixtures/rails2/Gemfile +8 -0
  43. data/fixtures/rails2/Rakefile +14 -0
  44. data/fixtures/rails2/app/controllers/application_controller.rb +10 -0
  45. data/fixtures/rails2/app/controllers/posts_controller.rb +15 -0
  46. data/fixtures/rails2/app/controllers/users_controller.rb +15 -0
  47. data/fixtures/rails2/config/boot.rb +129 -0
  48. data/fixtures/rails2/config/database.yml +16 -0
  49. data/fixtures/rails2/config/environment.rb +42 -0
  50. data/fixtures/rails2/config/environments/development.rb +17 -0
  51. data/fixtures/rails2/config/environments/production.rb +28 -0
  52. data/fixtures/rails2/config/environments/test.rb +28 -0
  53. data/fixtures/rails2/config/initializers/backtrace_silencers.rb +7 -0
  54. data/fixtures/rails2/config/initializers/cookie_verification_secret.rb +7 -0
  55. data/fixtures/rails2/config/initializers/inflections.rb +10 -0
  56. data/fixtures/rails2/config/initializers/mime_types.rb +5 -0
  57. data/fixtures/rails2/config/initializers/new_rails_defaults.rb +21 -0
  58. data/fixtures/rails2/config/initializers/session_store.rb +15 -0
  59. data/fixtures/rails2/config/locales/en.yml +5 -0
  60. data/fixtures/rails2/config/preinitializer.rb +20 -0
  61. data/fixtures/rails2/config/routes.rb +45 -0
  62. data/fixtures/rails2/db/schema.rb +40 -0
  63. data/fixtures/rails2/db/seeds.rb +7 -0
  64. data/fixtures/rails2/public/404.html +30 -0
  65. data/fixtures/rails2/public/422.html +30 -0
  66. data/fixtures/rails2/public/500.html +30 -0
  67. data/fixtures/rails2/public/favicon.ico +0 -0
  68. data/fixtures/rails2/public/images/rails.png +0 -0
  69. data/fixtures/rails2/public/index.html +275 -0
  70. data/fixtures/rails2/public/robots.txt +5 -0
  71. data/fixtures/rails2/script/about +4 -0
  72. data/fixtures/rails2/script/console +3 -0
  73. data/fixtures/rails2/script/dbconsole +3 -0
  74. data/fixtures/rails2/script/destroy +3 -0
  75. data/fixtures/rails2/script/generate +3 -0
  76. data/fixtures/rails2/script/performance/benchmarker +3 -0
  77. data/fixtures/rails2/script/performance/profiler +3 -0
  78. data/fixtures/rails2/script/plugin +3 -0
  79. data/fixtures/rails2/script/runner +3 -0
  80. data/fixtures/rails2/script/server +3 -0
  81. data/fixtures/rails2/test/functionals/posts_controller_test.rb +108 -0
  82. data/fixtures/rails2/test/functionals/users_controller_test.rb +87 -0
  83. data/fixtures/rails2/test/test_helper.rb +33 -0
  84. data/fixtures/rails3/.gitignore +4 -0
  85. data/fixtures/rails3/Gemfile +37 -0
  86. data/fixtures/rails3/Rakefile +12 -0
  87. data/fixtures/rails3/app/controllers/application_controller.rb +14 -0
  88. data/fixtures/rails3/app/controllers/posts_controller.rb +11 -0
  89. data/fixtures/rails3/app/controllers/users_controller.rb +11 -0
  90. data/fixtures/rails3/config.ru +4 -0
  91. data/fixtures/rails3/config/application.rb +42 -0
  92. data/fixtures/rails3/config/boot.rb +6 -0
  93. data/fixtures/rails3/config/database.yml +22 -0
  94. data/fixtures/rails3/config/environment.rb +5 -0
  95. data/fixtures/rails3/config/environments/development.rb +26 -0
  96. data/fixtures/rails3/config/environments/production.rb +49 -0
  97. data/fixtures/rails3/config/environments/test.rb +35 -0
  98. data/fixtures/rails3/config/initializers/backtrace_silencers.rb +7 -0
  99. data/fixtures/rails3/config/initializers/inflections.rb +10 -0
  100. data/fixtures/rails3/config/initializers/mime_types.rb +5 -0
  101. data/fixtures/rails3/config/initializers/secret_token.rb +7 -0
  102. data/fixtures/rails3/config/initializers/session_store.rb +8 -0
  103. data/fixtures/rails3/config/locales/en.yml +5 -0
  104. data/fixtures/rails3/config/routes.rb +61 -0
  105. data/fixtures/rails3/db/seeds.rb +7 -0
  106. data/fixtures/rails3/lib/tasks/.gitkeep +0 -0
  107. data/fixtures/rails3/public/404.html +26 -0
  108. data/fixtures/rails3/public/422.html +26 -0
  109. data/fixtures/rails3/public/500.html +26 -0
  110. data/fixtures/rails3/public/favicon.ico +0 -0
  111. data/fixtures/rails3/public/images/rails.png +0 -0
  112. data/fixtures/rails3/public/index.html +239 -0
  113. data/fixtures/rails3/public/robots.txt +5 -0
  114. data/fixtures/rails3/public/stylesheets/.gitkeep +0 -0
  115. data/fixtures/rails3/script/rails +6 -0
  116. data/fixtures/rails3/test/functional/posts_controller_test.rb +108 -0
  117. data/fixtures/rails3/test/functional/users_controller_test.rb +87 -0
  118. data/fixtures/rails3/test/test_helper.rb +26 -0
  119. data/fixtures/sinatra_test/Gemfile +13 -0
  120. data/fixtures/sinatra_test/Rakefile +6 -0
  121. data/fixtures/sinatra_test/app.rb +44 -0
  122. data/fixtures/sinatra_test/config.ru +7 -0
  123. data/fixtures/sinatra_test/test/functional/posts_controller_test.rb +108 -0
  124. data/fixtures/sinatra_test/test/functional/users_controller_test.rb +87 -0
  125. data/fixtures/sinatra_test/test/test_helper.rb +19 -0
  126. data/lib/rabl.rb +13 -1
  127. data/lib/rabl/builder.rb +14 -7
  128. data/lib/rabl/configuration.rb +41 -1
  129. data/lib/rabl/engine.rb +29 -19
  130. data/lib/rabl/helpers.rb +45 -18
  131. data/lib/rabl/template.rb +1 -1
  132. data/lib/rabl/version.rb +1 -1
  133. data/rabl.gemspec +6 -5
  134. data/test/builder_test.rb +4 -4
  135. data/test/configuration_test.rb +7 -22
  136. data/test/engine_test.rb +63 -44
  137. data/test/helpers_test.rb +68 -0
  138. data/test/integration/posts_controller_test.rb +108 -0
  139. data/test/integration/test_init.rb +35 -0
  140. data/test/integration/users_controller_test.rb +87 -0
  141. data/test/models/ormless.rb +2 -0
  142. data/test/models/user.rb +17 -6
  143. data/test/msgpack_engine_test.rb +332 -0
  144. data/test/silence.rb +21 -0
  145. data/test/teststrap.rb +22 -6
  146. metadata +160 -14
data/test/engine_test.rb CHANGED
@@ -2,6 +2,7 @@ require File.expand_path('../teststrap', __FILE__)
2
2
  require File.expand_path('../../lib/rabl', __FILE__)
3
3
  require File.expand_path('../../lib/rabl/template', __FILE__)
4
4
  require File.expand_path('../models/user', __FILE__)
5
+ require File.expand_path('../models/ormless', __FILE__)
5
6
 
6
7
  context "Rabl::Engine" do
7
8
 
@@ -45,6 +46,24 @@ context "Rabl::Engine" do
45
46
  scope.instance_variable_set :@user, User.new
46
47
  template.render(scope)
47
48
  end.equals "{\"person\":{}}"
49
+
50
+
51
+ asserts "that it can use non-ORM objects" do
52
+ template = rabl %q{
53
+ object @other
54
+ }
55
+ scope = Object.new
56
+ scope.instance_variable_set :@other, Ormless.new
57
+ template.render(scope)
58
+ end.equals "{\"ormless\":{}}"
59
+
60
+ asserts "that it works with nested controllers" do
61
+ template = rabl ""
62
+ scope = NestedScope::User.new
63
+ scope.instance_variable_set :@user, User.new
64
+ template.render(scope)
65
+ end.matches "{}"
66
+
48
67
  end
49
68
 
50
69
  context "#collection" do
@@ -58,15 +77,24 @@ context "Rabl::Engine" do
58
77
  template.render(scope)
59
78
  end.equals "[{\"user\":{}},{\"user\":{}}]"
60
79
 
61
- asserts "that it sets root node for objects" do
62
- template = rabl %{
63
- collection @users => :person
80
+ # TODO fix this test
81
+ # asserts "that it sets root node for objects" do
82
+ # template = rabl %{
83
+ # collection @users => :people
84
+ # }
85
+ # scope = Object.new
86
+ # scope.instance_variable_set :@users, [User.new, User.new]
87
+ # template.render(scope)
88
+ # end.equals "{\"people\":[{\"person\":{}},{\"person\":{}}]}"
89
+
90
+ asserts "that it can use non-ORM objects" do
91
+ template = rabl %q{
92
+ object @others
64
93
  }
65
94
  scope = Object.new
66
- scope.instance_variable_set :@users, [User.new, User.new]
95
+ scope.instance_variable_set :@others, [Ormless.new, Ormless.new]
67
96
  template.render(scope)
68
- end.equals "{\"person\":[{\"person\":{}},{\"person\":{}}]}"
69
-
97
+ end.equals "[{\"ormless\":{}},{\"ormless\":{}}]"
70
98
  end
71
99
 
72
100
  context "#attribute" do
@@ -78,8 +106,8 @@ context "Rabl::Engine" do
78
106
  }
79
107
  scope = Object.new
80
108
  scope.instance_variable_set :@user, User.new(:name => 'irvine')
81
- template.render(scope)
82
- end.equals "{\"user\":{\"name\":\"irvine\"}}"
109
+ template.render(scope).split('').sort
110
+ end.equals "{\"user\":{\"name\":\"irvine\"}}".split('').sort
83
111
 
84
112
  asserts "that it can add attribute under a different key name through :as" do
85
113
  template = rabl %{
@@ -88,8 +116,8 @@ context "Rabl::Engine" do
88
116
  }
89
117
  scope = Object.new
90
118
  scope.instance_variable_set :@user, User.new(:name => 'irvine')
91
- template.render(scope)
92
- end.equals "{\"user\":{\"city\":\"irvine\"}}"
119
+ template.render(scope).split('').sort
120
+ end.equals "{\"user\":{\"city\":\"irvine\"}}".split('').sort
93
121
 
94
122
  asserts "that it can add attribute under a different key name through hash" do
95
123
  template = rabl %{
@@ -98,8 +126,8 @@ context "Rabl::Engine" do
98
126
  }
99
127
  scope = Object.new
100
128
  scope.instance_variable_set :@user, User.new(:name => 'irvine')
101
- template.render(scope)
102
- end.equals "{\"user\":{\"city\":\"irvine\"}}"
129
+ template.render(scope).split('').sort
130
+ end.equals "{\"user\":{\"city\":\"irvine\"}}".split('').sort
103
131
 
104
132
  end
105
133
 
@@ -109,15 +137,27 @@ context "Rabl::Engine" do
109
137
  template = rabl %{
110
138
  code(:foo) { 'bar' }
111
139
  }
112
- template.render(Object.new)
113
- end.equals "{\"foo\":\"bar\"}"
140
+ template.render(Object.new).split('').sort
141
+ end.equals "{\"foo\":\"bar\"}".split('').sort
114
142
 
115
143
  asserts "that it can be passed conditionals" do
116
144
  template = rabl %{
117
145
  code(:foo, :if => lambda { |i| false }) { 'bar' }
118
146
  }
119
- template.render(Object.new)
120
- end.equals "{}"
147
+ template.render(Object.new).split('').sort
148
+ end.equals "{}".split('').sort
149
+
150
+ asserts "that it can merge the result with a collection element given no name" do
151
+ template = rabl %{
152
+ collection @users
153
+ code do |user|
154
+ {:name => user.name}
155
+ end
156
+ }
157
+ scope = Object.new
158
+ scope.instance_variable_set :@users, [User.new(:name => 'a'), User.new(:name => 'b')]
159
+ template.render(scope).split('').sort
160
+ end.equals "[{\"user\":{\"name\":\"a\"}},{\"user\":{\"name\":\"b\"}}]".split('').sort
121
161
 
122
162
  end
123
163
 
@@ -161,34 +201,9 @@ context "Rabl::Engine" do
161
201
  template.render(scope).split('').sort
162
202
  end.equals "{\"user\":{\"name\":\"leo\",\"city\":\"LA\",\"age\":12}}".split('').sort
163
203
  end
164
- end
165
-
166
- context "with json_engine" do
167
- setup do
168
- class CustomEncodeEngine
169
- def self.encode string, options = {}
170
- 42
171
- end
172
- end
173
-
174
- Rabl.configure do |config|
175
- config.json_engine = CustomEncodeEngine
176
- end
177
- end
178
-
179
- asserts 'that it returns process by custom to_json' do
180
- template = rabl %q{
181
- object @user
182
- }
183
- scope = Object.new
184
- scope.instance_variable_set :@user, User.new
185
- template.render(scope)
186
- end.equals 42
187
204
 
188
205
  teardown do
189
- Rabl.configure do |config|
190
- config.json_engine = MultiJson.default_engine
191
- end
206
+ Rabl.reset_configuration!
192
207
  end
193
208
  end
194
209
 
@@ -306,8 +321,8 @@ context "Rabl::Engine" do
306
321
  }
307
322
  scope = Object.new
308
323
  scope.instance_variable_set :@user, User.new(:name => 'leo', :city => 'LA')
309
- template.render(scope)
310
- end.equals "{\"name\":\"leo\",\"user\":{\"city\":\"LA\"}}"
324
+ template.render(scope).split('').sort
325
+ end.equals "{\"name\":\"leo\",\"user\":{\"city\":\"LA\"}}".split('').sort
311
326
 
312
327
  asserts "that it can create a child node with different key" do
313
328
  template = rabl %{
@@ -336,5 +351,9 @@ context "Rabl::Engine" do
336
351
  template.render(scope).split('').sort
337
352
  end.equals "{\"name\":\"leo\",\"city\":\"LA\",\"age\":12}".split('').sort
338
353
  end
354
+
355
+ teardown do
356
+ Rabl.reset_configuration!
357
+ end
339
358
  end
340
359
  end
@@ -0,0 +1,68 @@
1
+ require 'tmpdir'
2
+ require 'pathname'
3
+ require File.expand_path('../../lib/rabl', __FILE__)
4
+
5
+ class TestHelper
6
+ include Rabl::Helpers
7
+ end
8
+
9
+ context "Rabl::Helpers" do
10
+ context "fetch_source" do
11
+ helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
12
+
13
+ setup do
14
+ ::Rails = stub(Class.new)
15
+ ::Rails.root.returns(tmp_path)
16
+ File.open(tmp_path + "test.json.rabl", "w") do |f|
17
+ f.puts "content"
18
+ end
19
+ File.open(tmp_path + "test_v1.json.rabl", "w") do |f|
20
+ f.puts "content_v1"
21
+ end
22
+ FileUtils.touch tmp_path + "test_v2.json.rabl"
23
+ [TestHelper.new.fetch_source('test', :view_path => tmp_path.to_s),
24
+ TestHelper.new.fetch_source('test_v1', :view_path => tmp_path.to_s)]
25
+ end
26
+
27
+ asserts(:first).equals {["content\n", (tmp_path + "test.json.rabl").to_s ]}
28
+ asserts(:last).equals {["content_v1\n", (tmp_path + "test_v1.json.rabl").to_s ]}
29
+ teardown { Object.send(:remove_const, :Rails) }
30
+ end
31
+
32
+ context "fetch_source" do
33
+ helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
34
+
35
+ setup do
36
+ ::Rails = stub(Class.new)
37
+ ::Rails.root.returns(tmp_path)
38
+ File.open(tmp_path + "test.rabl", "w") do |f|
39
+ f.puts "content"
40
+ end
41
+ TestHelper.new.fetch_source('test', :view_path => tmp_path.to_s)
42
+ end
43
+ asserts('detects file.rabl') { topic }.equals do
44
+ ["content\n", (tmp_path + 'test.rabl').to_s]
45
+ end
46
+ teardown { Object.send(:remove_const, :Rails) }
47
+ end
48
+
49
+ context "fetch_source" do
50
+ helper(:tmp_path) { @tmp_path ||= Pathname.new(Dir.mktmpdir) }
51
+
52
+ setup do
53
+ ::Rails = stub(Class.new)
54
+ ::Rails.root.returns(tmp_path)
55
+ File.open(tmp_path + "test.rabl", "w") do |f|
56
+ f.puts "content"
57
+ end
58
+ File.open(tmp_path + "test.json.rabl", "w") do |f|
59
+ f.puts "content2"
60
+ end
61
+ TestHelper.new.fetch_source('test', :view_path => tmp_path.to_s)
62
+ end
63
+ asserts('detects file.json.rabl first') { topic }.equals do
64
+ ["content2\n", (tmp_path + 'test.json.rabl').to_s]
65
+ end
66
+ teardown { Object.send(:remove_const, :Rails) }
67
+ end
68
+ end
@@ -0,0 +1,108 @@
1
+ # Lives in <rabl>/test/integration/posts_controller_test.rb
2
+ # Symlinked to fixture applications
3
+
4
+ begin # Padrino
5
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_config.rb')
6
+ rescue LoadError # Rails
7
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper.rb')
8
+ end
9
+
10
+ context "PostsController" do
11
+ helper(:json_output) { JSON.parse(last_response.body) }
12
+
13
+ setup do
14
+ create_users!
15
+ Post.delete_all
16
+ @post1 = Post.create(:title => "Foo", :body => "Bar", :user_id => @user1.id)
17
+ @post2 = Post.create(:title => "Baz", :body => "Bah", :user_id => @user2.id)
18
+ @post3 = Post.create(:title => "Kaz", :body => "Paz", :user_id => @user3.id)
19
+ @posts = [@post1, @post2, @post3]
20
+ end
21
+
22
+ context "for index action" do
23
+ setup do
24
+ get "/posts"
25
+ end
26
+
27
+ # Attributes (regular)
28
+ asserts("contains post titles") do
29
+ json_output['articles'].map { |o| o["article"]["title"] }
30
+ end.equals { @posts.map(&:title) }
31
+
32
+ asserts("contains post bodies") do
33
+ json_output['articles'].map { |o| o["article"]["body"] }
34
+ end.equals { @posts.map(&:body) }
35
+
36
+ # Attributes (custom name)
37
+ asserts("contains post posted_at") do
38
+ json_output['articles'].map { |o| o["article"]["posted_at"] }
39
+ end.equals { @posts.map(&:created_at).map(&:iso8601) }
40
+
41
+ # Child
42
+ asserts("contains post user child username") do
43
+ json_output['articles'].map { |o| o["article"]["user"]["username"] }
44
+ end.equals { @posts.map(&:user).map(&:username) }
45
+
46
+ asserts("contains post user child role") do
47
+ json_output['articles'].map { |o| o["article"]["user"]["role"] }
48
+ end.equals { ["normal", "normal", "admin"] }
49
+
50
+ # Child Numbers of the Child User
51
+ asserts("contains post user child numbers") do
52
+ json_output['articles'].map { |o| o["article"]["user"]["pnumbers"][0]["pnumber"]["formatted"] }
53
+ end.equals { @posts.map(&:user).map(&:phone_numbers).map(&:first).map(&:formatted) }
54
+
55
+ # Glue (username to article)
56
+ asserts("contains glued usernames") do
57
+ json_output['articles'].map { |o| o["article"]["author_name"] }
58
+ end.equals { @posts.map(&:user).map(&:username) }
59
+
60
+ # Conditional Child (admin)
61
+ asserts("contains admin child only for admins") do
62
+ json_output['articles'].map { |o| o["article"]["admin"]["username"] if o["article"].has_key?("admin") }.compact
63
+ end.equals { [@user3.username] }
64
+
65
+ # Conditional Node (created_by_admin)
66
+ asserts("contains created_by_admin node for admins") do
67
+ json_output['articles'].last['article']['created_by_admin']
68
+ end.equals { true }
69
+
70
+ denies("contains no created_by_admin node for non-admins") do
71
+ json_output['articles'].first['article']
72
+ end.includes(:created_by_admin)
73
+ end # index action
74
+
75
+ context "for show action" do
76
+ setup do
77
+ get "/posts/#{@post1.id}"
78
+ json_output['post']
79
+ end
80
+
81
+ # Attributes (regular)
82
+ asserts("contains post title") { topic['title'] }.equals { @post1.title }
83
+ asserts("contains post body") { topic['body'] }.equals { @post1.body }
84
+
85
+ # Attributes (custom name)
86
+ asserts("contains post posted_at") { topic['posted_at'] }.equals { @post1.created_at.iso8601 }
87
+
88
+ # Child
89
+ asserts("contains post user child username") { topic["user"]["username"] }.equals { @post1.user.username }
90
+ asserts("contains post user child role") { topic["user"]["role"] }.equals { "normal" }
91
+
92
+ # Child Numbers of the Child User
93
+ asserts("contains post user child numbers") do
94
+ topic["user"]["pnumbers"][0]["pnumber"]["formatted"]
95
+ end.equals { @post1.user.phone_numbers[0].formatted }
96
+
97
+ # Glue (username to article)
98
+ asserts("contains glued username") { topic["author_name"] }.equals { @post1.user.username }
99
+
100
+ # Non-ORM Date Node Partial
101
+ context "for date node" do
102
+ setup { json_output['post']['created_date'] }
103
+ asserts("contains date partial with day") { topic['day'] }.equals { @post1.created_at.day }
104
+ asserts("contains date partial with hour") { topic['hour'] }.equals { @post1.created_at.hour }
105
+ asserts("contains date partial with full") { topic['full'] }.equals { @post1.created_at.iso8601 }
106
+ end # date node
107
+ end # show action
108
+ end
@@ -0,0 +1,35 @@
1
+ require 'rack/test'
2
+ require 'riot'
3
+
4
+ Riot.pretty_dots
5
+
6
+ class Riot::Situation
7
+ include Rack::Test::Methods
8
+
9
+ # Construct all the users needed for testing
10
+ def create_users!
11
+ User.delete_all; PhoneNumber.delete_all
12
+ @user1 = User.create!(:username => "billybob", :email => "billy@bob.com", :location => "SF", :is_admin => false)
13
+ @user2 = User.create!(:username => "joefrank", :email => "joe@frank.com", :location => "LA", :is_admin => false)
14
+ @user3 = User.create!(:username => "suziesmith", :email => "suzie@smith.com", :location => "NYC", :is_admin => true)
15
+ @users = [@user1, @user2, @user3]
16
+ pn_ops = { :area_code => "#{rand(9).to_s*3}", :prefix => "#{rand(9).to_s*3}", :suffix => "#{rand(9).to_s*4}"}
17
+ PhoneNumber.create(pn_ops.merge(:is_primary => true, :name => "Home", :user_id => @user1.id))
18
+ PhoneNumber.create(pn_ops.merge(:is_primary => false, :name => "Work", :user_id => @user1.id))
19
+ PhoneNumber.create(pn_ops.merge(:is_primary => true, :name => "Home", :user_id => @user2.id))
20
+ PhoneNumber.create(pn_ops.merge(:is_primary => true, :name => "Home", :user_id => @user3.id))
21
+ end
22
+ end
23
+
24
+ class Riot::Context
25
+ # Set the Rack app which is to be tested.
26
+ #
27
+ # context "MyApp" do
28
+ # app { [200, {}, "Hello!"] }
29
+ # setup { get '/' }
30
+ # asserts(:status).equals(200)
31
+ # end
32
+ def app(app=nil, &block)
33
+ setup { @app = (app || block.call) }
34
+ end
35
+ end
@@ -0,0 +1,87 @@
1
+ # Lives in <rabl>/test/integration/users_controller_test.rb
2
+ # Symlinked to fixture applications
3
+
4
+ begin # Sinatra
5
+ require File.expand_path(File.dirname(__FILE__) + '/../../test_config.rb')
6
+ rescue LoadError # Rails
7
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper.rb')
8
+ end
9
+
10
+ context "UsersController" do
11
+ helper(:json_output) { JSON.parse(last_response.body) }
12
+
13
+ setup do
14
+ create_users!
15
+ end
16
+
17
+ context "for index action" do
18
+ # Tests `collection @users` extending from 'show' template
19
+
20
+ setup do
21
+ get "/users"
22
+ end
23
+
24
+ # Attributes (regular)
25
+ asserts("contains user usernames") do
26
+ json_output.map { |u| u["user"]["username"] }
27
+ end.equals { @users.map(&:username) }
28
+ asserts("contains email") do
29
+ json_output.map { |u| u["user"]["email"] }
30
+ end.equals { @users.map(&:email) }
31
+ asserts("contains location") do
32
+ json_output.map { |u| u["user"]["location"] }
33
+ end.equals { @users.map(&:location) }
34
+
35
+ # Attributes (custom name)
36
+ asserts("contains registered_at") do
37
+ json_output.map { |u| u["user"]["registered_at"] }
38
+ end.equals { @users.map(&:created_at).map(&:iso8601) }
39
+
40
+ # Node (renders based on attribute)
41
+ asserts("contains role") do
42
+ json_output.map { |u| u["user"]["role"] }
43
+ end.equals ['normal', 'normal', 'admin']
44
+
45
+ # Child (custom collection name)
46
+ asserts("contains formatted phone numbers") do
47
+ json_output.map { |u| u["user"]["pnumbers"].map { |n| n["pnumber"]["formatted"] } }
48
+ end.equals { @users.map { |u| u.phone_numbers.map(&:formatted) } }
49
+
50
+ # Node (renders collection partial)
51
+ asserts("contains formatted node numbers") do
52
+ json_output.map { |u| u["user"]["node_numbers"].map { |n| n["formatted"] } }
53
+ end.equals { @users.map { |u| u.phone_numbers.map(&:formatted) } }
54
+ end # index
55
+
56
+ context "for show action" do
57
+ # Tests `object :user => :person` custom parent node name
58
+ setup do
59
+ get "/users/#{@user1.id}"
60
+ end
61
+
62
+ # Attributes (regular)
63
+ asserts("contains username") { json_output["person"]["username"] }.equals { @user1.username }
64
+ asserts("contains email") { json_output["person"]["email"] }.equals { @user1.email }
65
+ asserts("contains location") { json_output["person"]["location"] }.equals { @user1.location }
66
+ # Attributes (custom name)
67
+ asserts("contains registered_at") { json_output["person"]["registered_at"] }.equals { @user1.created_at.iso8601 }
68
+ # Node (renders based on attribute)
69
+ asserts("contains role node") { json_output["person"]["role"] }.equals "normal"
70
+
71
+ # Child (custom collection name)
72
+ asserts("contains first phone number") {
73
+ json_output["person"]["pnumbers"][0]["pnumber"]["formatted"]
74
+ }.equals { @user1.phone_numbers[0].formatted }
75
+ asserts("contains second phone number") {
76
+ json_output["person"]["pnumbers"][1]["pnumber"]["formatted"]
77
+ }.equals { @user1.phone_numbers[1].formatted }
78
+
79
+ # Node (renders collection partial)
80
+ asserts("contains first node number") {
81
+ json_output["person"]["node_numbers"][0]["formatted"]
82
+ }.equals { @user1.phone_numbers[0].formatted }
83
+ asserts("contains second node number") {
84
+ json_output["person"]["node_numbers"][1]["formatted"]
85
+ }.equals { @user1.phone_numbers[1].formatted }
86
+ end # show
87
+ end