standardapi 6.0.0.26 → 6.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -6
- data/lib/standard_api.rb +5 -0
- data/lib/standard_api/access_control_list.rb +114 -0
- data/lib/standard_api/active_record/connection_adapters/postgresql/schema_statements.rb +21 -0
- data/lib/standard_api/controller.rb +75 -78
- data/lib/standard_api/errors.rb +9 -0
- data/lib/standard_api/helpers.rb +66 -13
- data/lib/standard_api/includes.rb +9 -0
- data/lib/standard_api/middleware/query_encoding.rb +3 -3
- data/lib/standard_api/railtie.rb +13 -2
- data/lib/standard_api/route_helpers.rb +5 -5
- data/lib/standard_api/test_case.rb +24 -14
- data/lib/standard_api/test_case/calculate_tests.rb +10 -4
- data/lib/standard_api/test_case/create_tests.rb +13 -15
- data/lib/standard_api/test_case/index_tests.rb +14 -4
- data/lib/standard_api/test_case/schema_tests.rb +25 -3
- data/lib/standard_api/test_case/show_tests.rb +1 -0
- data/lib/standard_api/test_case/update_tests.rb +8 -9
- data/lib/standard_api/version.rb +1 -1
- data/lib/standard_api/views/application/_record.json.jbuilder +33 -30
- data/lib/standard_api/views/application/_record.streamer +36 -34
- data/lib/standard_api/views/application/_schema.json.jbuilder +68 -0
- data/lib/standard_api/views/application/_schema.streamer +78 -0
- data/lib/standard_api/views/application/new.streamer +1 -1
- data/lib/standard_api/views/application/schema.json.jbuilder +1 -12
- data/lib/standard_api/views/application/schema.streamer +1 -16
- data/test/standard_api/caching_test.rb +43 -0
- data/test/standard_api/helpers_test.rb +172 -0
- data/test/standard_api/performance.rb +39 -0
- data/test/standard_api/route_helpers_test.rb +33 -0
- data/test/standard_api/standard_api_test.rb +699 -0
- data/test/standard_api/test_app.rb +1 -0
- data/test/standard_api/test_app/app/controllers/acl/account_acl.rb +15 -0
- data/test/standard_api/test_app/app/controllers/acl/property_acl.rb +27 -0
- data/test/standard_api/test_app/app/controllers/acl/reference_acl.rb +7 -0
- data/test/standard_api/test_app/controllers.rb +13 -45
- data/test/standard_api/test_app/models.rb +38 -4
- data/test/standard_api/test_app/test/factories.rb +4 -3
- data/test/standard_api/test_app/views/photos/_photo.json.jbuilder +1 -0
- data/test/standard_api/test_app/views/photos/_photo.streamer +18 -0
- data/test/standard_api/test_app/views/photos/_schema.json.jbuilder +1 -0
- data/test/standard_api/test_app/views/photos/_schema.streamer +3 -0
- data/test/standard_api/test_app/views/photos/schema.json.jbuilder +1 -1
- data/test/standard_api/test_app/views/photos/schema.streamer +1 -0
- data/test/standard_api/test_helper.rb +238 -0
- metadata +33 -17
- data/test/standard_api/test_app/log/test.log +0 -129516
@@ -37,6 +37,7 @@ require 'standard_api/test_app/controllers'
|
|
37
37
|
# Test Application Routes
|
38
38
|
Rails.application.routes.draw do
|
39
39
|
get :tables, to: 'application#tables', as: :tables
|
40
|
+
get :schema, to: 'application#schema', as: :schema
|
40
41
|
|
41
42
|
[:properties, :photos, :documents, :references, :sessions, :unlimited, :default_limit].each do |r|
|
42
43
|
standard_resources r
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module PropertyACL
|
2
|
+
|
3
|
+
def attributes
|
4
|
+
[ :name,
|
5
|
+
:aliases,
|
6
|
+
:description,
|
7
|
+
:constructed,
|
8
|
+
:size,
|
9
|
+
:active
|
10
|
+
# :photos_attributes,
|
11
|
+
# { photos_attributes: [ :id, :account_id, :property_id, :format] }
|
12
|
+
]
|
13
|
+
end
|
14
|
+
|
15
|
+
def orders
|
16
|
+
["id", "name", "aliases", "description", "constructed", "size", "created_at", "active"]
|
17
|
+
end
|
18
|
+
|
19
|
+
def includes
|
20
|
+
[ :photos, :landlord, :english_name, :document ]
|
21
|
+
end
|
22
|
+
|
23
|
+
def nested
|
24
|
+
[ :photos ]
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -1,77 +1,45 @@
|
|
1
1
|
class ApplicationController < ActionController::Base
|
2
2
|
include StandardAPI::Controller
|
3
|
+
include StandardAPI::AccessControlList
|
3
4
|
prepend_view_path File.join(File.dirname(__FILE__), 'views')
|
4
5
|
|
5
|
-
private
|
6
|
-
|
7
|
-
def account_params
|
8
|
-
[ "property_id", "name" ]
|
9
|
-
end
|
10
|
-
|
11
|
-
def account_orders
|
12
|
-
[ "id" ]
|
13
|
-
end
|
14
|
-
|
15
|
-
def account_includes
|
16
|
-
[ "photos" ]
|
17
|
-
end
|
18
|
-
|
19
|
-
def property_params
|
20
|
-
[ :name,
|
21
|
-
:aliases,
|
22
|
-
:description,
|
23
|
-
:constructed,
|
24
|
-
:size,
|
25
|
-
:active,
|
26
|
-
:photos_attributes,
|
27
|
-
{ photos_attributes: [ :id, :account_id, :property_id, :format] }
|
28
|
-
]
|
29
|
-
end
|
30
|
-
|
31
|
-
def property_orders
|
32
|
-
["id", "name", "aliases", "description", "constructed", "size", "created_at", "active"]
|
33
|
-
end
|
34
|
-
|
35
|
-
def property_includes
|
36
|
-
[:photos, :landlord, :english_name]
|
37
|
-
end
|
38
|
-
|
39
|
-
def reference_includes
|
40
|
-
{ subject: [ :landlord, :photos ] }
|
41
|
-
end
|
42
|
-
|
43
6
|
end
|
44
7
|
|
45
8
|
class PropertiesController < ApplicationController
|
46
9
|
end
|
47
10
|
|
48
11
|
class AccountsController < ApplicationController
|
12
|
+
|
13
|
+
def show
|
14
|
+
@account = Account.last
|
15
|
+
end
|
16
|
+
|
49
17
|
end
|
50
18
|
|
51
19
|
class DocumentsController < ApplicationController
|
52
20
|
|
53
|
-
def
|
21
|
+
def document_attributes
|
54
22
|
[ :file, :type ]
|
55
23
|
end
|
56
|
-
|
24
|
+
|
57
25
|
def document_orders
|
58
|
-
[:id]
|
26
|
+
[ :id ]
|
59
27
|
end
|
60
28
|
|
61
29
|
end
|
62
30
|
|
63
31
|
class PhotosController < ApplicationController
|
64
32
|
|
65
|
-
def
|
33
|
+
def photo_attributes
|
66
34
|
[ :id, :account_id, :property_id, :format ]
|
67
35
|
end
|
68
36
|
|
69
37
|
def photo_orders
|
70
|
-
[:id]
|
38
|
+
[ :id ]
|
71
39
|
end
|
72
40
|
|
73
41
|
def photo_includes
|
74
|
-
[:account]
|
42
|
+
[ :account ]
|
75
43
|
end
|
76
44
|
|
77
45
|
end
|
@@ -104,4 +72,4 @@ class DefaultLimitController < ApplicationController
|
|
104
72
|
100
|
105
73
|
end
|
106
74
|
|
107
|
-
end
|
75
|
+
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
# = Models
|
2
2
|
|
3
3
|
class Account < ActiveRecord::Base
|
4
|
-
has_many :photos
|
4
|
+
has_many :photos, -> { order(:created_at) }
|
5
5
|
belongs_to :property
|
6
|
+
belongs_to :subject, polymorphic: true
|
6
7
|
end
|
7
8
|
|
8
9
|
class Photo < ActiveRecord::Base
|
@@ -21,6 +22,9 @@ class Property < ActiveRecord::Base
|
|
21
22
|
has_and_belongs_to_many :photos
|
22
23
|
has_many :accounts
|
23
24
|
has_one :landlord, class_name: 'Account'
|
25
|
+
has_one :document_attachments, class_name: "Attachment", as: :record, inverse_of: :record
|
26
|
+
has_one :document, through: "document_attachments"
|
27
|
+
|
24
28
|
|
25
29
|
validates :name, presence: true
|
26
30
|
accepts_nested_attributes_for :photos
|
@@ -34,22 +38,46 @@ class Reference < ActiveRecord::Base
|
|
34
38
|
belongs_to :subject, polymorphic: true
|
35
39
|
end
|
36
40
|
|
41
|
+
class Document < ActiveRecord::Base
|
42
|
+
attr_accessor :file
|
43
|
+
end
|
44
|
+
|
45
|
+
class Attachment < ActiveRecord::Base
|
46
|
+
belongs_to :record, polymorphic: true
|
47
|
+
belongs_to :document
|
48
|
+
end
|
49
|
+
|
37
50
|
# = Migration
|
38
51
|
|
39
|
-
class CreateModelTables < ActiveRecord::Migration[
|
52
|
+
class CreateModelTables < ActiveRecord::Migration[6.0]
|
40
53
|
|
41
54
|
def self.up
|
42
55
|
|
56
|
+
comment = "test comment"
|
57
|
+
exec_query(<<-SQL, "SQL")
|
58
|
+
COMMENT ON DATABASE #{quote_column_name(current_database)} IS #{quote(comment)};
|
59
|
+
SQL
|
60
|
+
|
43
61
|
create_table "accounts", force: :cascade do |t|
|
44
62
|
t.string 'name', limit: 255
|
45
63
|
t.integer 'property_id'
|
64
|
+
t.integer "subject_id"
|
65
|
+
t.string "subject_type"
|
66
|
+
t.datetime "property_cached_at"
|
67
|
+
t.datetime "subject_cached_at"
|
46
68
|
t.integer 'photos_count', null: false, default: 0
|
69
|
+
t.datetime "created_at", null: false
|
70
|
+
end
|
71
|
+
|
72
|
+
create_table "landlords", force: :cascade do |t|
|
73
|
+
t.string "name"
|
47
74
|
end
|
48
75
|
|
49
76
|
create_table "photos", force: :cascade do |t|
|
50
77
|
t.integer "account_id"
|
51
78
|
t.integer "property_id"
|
52
79
|
t.string "format", limit: 255
|
80
|
+
t.datetime "created_at", null: false
|
53
81
|
end
|
54
82
|
|
55
83
|
create_table "properties", force: :cascade do |t|
|
@@ -68,12 +96,12 @@ class CreateModelTables < ActiveRecord::Migration[5.2]
|
|
68
96
|
t.string "key"
|
69
97
|
t.string "value"
|
70
98
|
end
|
71
|
-
|
99
|
+
|
72
100
|
create_table "photos_properties", force: :cascade do |t|
|
73
101
|
t.integer "photo_id"
|
74
102
|
t.integer "property_id"
|
75
103
|
end
|
76
|
-
|
104
|
+
|
77
105
|
create_table "landlords_properties", force: :cascade do |t|
|
78
106
|
t.integer "landlord_id"
|
79
107
|
t.integer "property_id"
|
@@ -82,6 +110,12 @@ class CreateModelTables < ActiveRecord::Migration[5.2]
|
|
82
110
|
create_table "documents", force: :cascade do |t|
|
83
111
|
t.string 'type'
|
84
112
|
end
|
113
|
+
|
114
|
+
create_table "attachments", force: :cascade do |t|
|
115
|
+
t.string 'record_type'
|
116
|
+
t.integer 'record_id'
|
117
|
+
t.integer 'document_id'
|
118
|
+
end
|
85
119
|
end
|
86
120
|
|
87
121
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
FactoryBot.define do
|
2
|
+
|
2
3
|
factory :account do
|
3
4
|
name { Faker::Name.name }
|
4
5
|
|
@@ -7,7 +8,7 @@ FactoryBot.define do
|
|
7
8
|
name { nil }
|
8
9
|
end
|
9
10
|
end
|
10
|
-
|
11
|
+
|
11
12
|
factory :landlord do
|
12
13
|
name { Faker::Name.name }
|
13
14
|
end
|
@@ -17,12 +18,12 @@ FactoryBot.define do
|
|
17
18
|
end
|
18
19
|
|
19
20
|
factory :document do
|
20
|
-
file {
|
21
|
+
file { Rack::Test::UploadedFile.new(File.join(Rails.root, 'test/fixtures/photo.png'), 'image/png') }
|
21
22
|
end
|
22
23
|
|
23
24
|
factory :pdf do
|
24
25
|
type { 'Pdf' }
|
25
|
-
file {
|
26
|
+
file { Rack::Test::UploadedFile.new(File.join(Rails.root, 'test/fixtures/photo.png'), 'image/png') }
|
26
27
|
end
|
27
28
|
|
28
29
|
factory :reference do
|
@@ -0,0 +1,18 @@
|
|
1
|
+
json.object! do
|
2
|
+
json.set! :id, photo.id
|
3
|
+
json.set! :account_id, photo.account_id
|
4
|
+
json.set! :property_id, photo.property_id
|
5
|
+
json.set! :format, photo.format
|
6
|
+
json.set! :created_at, photo.created_at
|
7
|
+
json.set! :template, 'photos/_photo'
|
8
|
+
|
9
|
+
if includes[:account]
|
10
|
+
json.set! :account do
|
11
|
+
if photo.account
|
12
|
+
json.partial! 'application/record', record: photo.account, includes: includes[:account]
|
13
|
+
else
|
14
|
+
json.value! nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
json.set! 'template', 'photos/schema'
|
@@ -1 +1 @@
|
|
1
|
-
json.
|
1
|
+
json.partial! 'schema'
|
@@ -0,0 +1 @@
|
|
1
|
+
json.partial! 'schema'
|
@@ -0,0 +1,238 @@
|
|
1
|
+
require File.expand_path('../test_app', __FILE__)
|
2
|
+
|
3
|
+
require "minitest/autorun"
|
4
|
+
require 'minitest/unit'
|
5
|
+
require 'factory_bot'
|
6
|
+
require 'faker'
|
7
|
+
require 'standard_api/test_case'
|
8
|
+
require 'byebug'
|
9
|
+
require 'mocha/minitest'
|
10
|
+
|
11
|
+
# Setup the test db
|
12
|
+
ActiveSupport.test_order = :random
|
13
|
+
|
14
|
+
include ActionDispatch::TestProcess
|
15
|
+
|
16
|
+
class ActiveSupport::TestCase
|
17
|
+
include ActiveRecord::TestFixtures
|
18
|
+
include FactoryBot::Syntax::Methods
|
19
|
+
|
20
|
+
def setup
|
21
|
+
@routes ||= TestApplication.routes
|
22
|
+
@subscribers, @layouts, @partials = [], {}, {}
|
23
|
+
|
24
|
+
Rails.cache.clear
|
25
|
+
|
26
|
+
@subscribers << ActiveSupport::Notifications.subscribe("!render_template.action_view") do |_name, _start, _finish, _id, payload|
|
27
|
+
path = payload[:identifier]
|
28
|
+
virtual_path = payload[:virtual_path]
|
29
|
+
format, handler = *path.split("/").last.split('.').last(2)
|
30
|
+
|
31
|
+
partial = virtual_path =~ /^.*\/_[^\/]*$/
|
32
|
+
|
33
|
+
if partial
|
34
|
+
if @partials[virtual_path]
|
35
|
+
@partials[virtual_path][:count] += 1
|
36
|
+
else
|
37
|
+
@partials[virtual_path] = {
|
38
|
+
count: 1,
|
39
|
+
path: virtual_path,
|
40
|
+
format: format,
|
41
|
+
handler: handler
|
42
|
+
}
|
43
|
+
end
|
44
|
+
else
|
45
|
+
if @layouts[virtual_path]
|
46
|
+
@layouts[virtual_path][:count] += 1
|
47
|
+
else
|
48
|
+
@layouts[virtual_path] = {
|
49
|
+
count: 1,
|
50
|
+
path: virtual_path,
|
51
|
+
format: format,
|
52
|
+
handler: handler
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def teardown
|
60
|
+
@subscribers.each do |subscriber|
|
61
|
+
ActiveSupport::Notifications.unsubscribe(subscriber)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# = Helper Methods
|
66
|
+
|
67
|
+
def controller_path
|
68
|
+
if defined?(@controller)
|
69
|
+
@controller.controller_path
|
70
|
+
else
|
71
|
+
controller_class.new.controller_path
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def path_with_action(action, options={})
|
76
|
+
{ :controller => controller_path, :action => action }.merge(options)
|
77
|
+
end
|
78
|
+
|
79
|
+
def assert_sql(sql, &block)
|
80
|
+
queries = []
|
81
|
+
callback = -> (*, payload) do
|
82
|
+
queries << payload[:sql]
|
83
|
+
end
|
84
|
+
|
85
|
+
ActiveSupport::Notifications.subscribed(callback, "sql.active_record", &block)
|
86
|
+
|
87
|
+
assert_not_nil queries.map { |x| x.strip.gsub(/\s+/, ' ') }.
|
88
|
+
find { |x| x == sql.strip.gsub(/\s+/, ' ') }
|
89
|
+
end
|
90
|
+
|
91
|
+
def assert_rendered(options = {}, message = nil)
|
92
|
+
options = case options
|
93
|
+
when NilClass, Regexp, String, Symbol
|
94
|
+
{ layout: options }
|
95
|
+
when Hash
|
96
|
+
options
|
97
|
+
else
|
98
|
+
raise ArgumentError, "assert_template only accepts a String, Symbol, Hash, Regexp, or nil"
|
99
|
+
end
|
100
|
+
|
101
|
+
options.assert_valid_keys(:layout, :partial, :count, :format, :handler)
|
102
|
+
|
103
|
+
if expected_layout = options[:layout]
|
104
|
+
case expected_layout
|
105
|
+
when String, Symbol
|
106
|
+
msg = message || sprintf("expecting layout <%s> but action rendered <%s>",
|
107
|
+
expected_layout, @layouts.keys)
|
108
|
+
assert_includes @layouts.keys, expected_layout.to_s, msg
|
109
|
+
|
110
|
+
key = expected_layout.to_s
|
111
|
+
value = @layouts[key]
|
112
|
+
|
113
|
+
if expected_count = options[:count]
|
114
|
+
actual_count = value[:count]
|
115
|
+
msg = message || sprintf("expecting %s to be rendered %s time(s) but rendered %s time(s)",
|
116
|
+
expected_partial, expected_count, actual_count)
|
117
|
+
assert_equal expected_count, actual_count, msg
|
118
|
+
end
|
119
|
+
|
120
|
+
if expected_format = options[:format]
|
121
|
+
actual_format = value[:format]
|
122
|
+
msg = message || sprintf("expecting %s to be rendered as %s but rendered as %s",
|
123
|
+
expected_partial, expected_format, actual_format)
|
124
|
+
assert_equal expected_format, actual_format, msg
|
125
|
+
end
|
126
|
+
|
127
|
+
if expected_handler = options[:handler]
|
128
|
+
actual_handler = value[:handler]
|
129
|
+
msg = message || sprintf("expecting %s to be rendered as %s but rendered as %s",
|
130
|
+
expected_partial, expected_handler, actual_handler)
|
131
|
+
assert_equal expected_handler, actual_handler, msg
|
132
|
+
end
|
133
|
+
when Regexp
|
134
|
+
msg = message || sprintf("expecting layout <%s> but action rendered <%s>",
|
135
|
+
expected_layout, @layouts.keys)
|
136
|
+
assert(@layouts.keys.any? {|l| l =~ expected_layout }, msg)
|
137
|
+
|
138
|
+
key = @layouts.keys.find {|l| l =~ expected_layout }
|
139
|
+
value = @layouts[key]
|
140
|
+
|
141
|
+
if expected_count = options[:count]
|
142
|
+
actual_count = value[:count]
|
143
|
+
msg = message || sprintf("expecting %s to be rendered %s time(s) but rendered %s time(s)",
|
144
|
+
expected_partial, expected_count, actual_count)
|
145
|
+
assert_equal expected_count, actual_count, msg
|
146
|
+
end
|
147
|
+
|
148
|
+
if expected_format = options[:format]
|
149
|
+
actual_format = value[:format]
|
150
|
+
msg = message || sprintf("expecting %s to be rendered as %s but rendered as %s",
|
151
|
+
expected_partial, expected_format, actual_format)
|
152
|
+
assert_equal expected_format, actual_format, msg
|
153
|
+
end
|
154
|
+
|
155
|
+
if expected_handler = options[:handler]
|
156
|
+
actual_handler = value[:handler]
|
157
|
+
msg = message || sprintf("expecting %s to be rendered as %s but rendered as %s",
|
158
|
+
expected_partial, expected_handler, actual_handler)
|
159
|
+
assert_equal expected_handler, actual_handler, msg
|
160
|
+
end
|
161
|
+
when nil, false
|
162
|
+
assert(@layouts.empty?, msg)
|
163
|
+
end
|
164
|
+
elsif expected_partial = options[:partial]
|
165
|
+
case expected_partial
|
166
|
+
when String, Symbol
|
167
|
+
msg = message || sprintf("expecting partial <%s> but action rendered <%s>",
|
168
|
+
expected_partial, @partials.keys)
|
169
|
+
assert_includes @partials.keys, expected_partial.to_s, msg
|
170
|
+
|
171
|
+
key = expected_partial.to_s
|
172
|
+
value = @partials[key]
|
173
|
+
|
174
|
+
if expected_count = options[:count]
|
175
|
+
actual_count = value[:count]
|
176
|
+
msg = message || sprintf("expecting %s to be rendered %s time(s) but rendered %s time(s)",
|
177
|
+
expected_partial, expected_count, actual_count)
|
178
|
+
assert_equal expected_count, actual_count, msg
|
179
|
+
end
|
180
|
+
|
181
|
+
if expected_format = options[:format]
|
182
|
+
actual_format = value[:format]
|
183
|
+
msg = message || sprintf("expecting %s to be rendered as %s but rendered as %s",
|
184
|
+
expected_partial, expected_format, actual_format)
|
185
|
+
assert_equal expected_format, actual_format, msg
|
186
|
+
end
|
187
|
+
|
188
|
+
if expected_handler = options[:handler]
|
189
|
+
actual_handler = value[:handler]
|
190
|
+
msg = message || sprintf("expecting %s to be rendered as %s but rendered as %s",
|
191
|
+
expected_partial, expected_handler, actual_handler)
|
192
|
+
assert_equal expected_handler, actual_handler, msg
|
193
|
+
end
|
194
|
+
when Regexp
|
195
|
+
msg = message || sprintf("expecting partial <%s> but action rendered <%s>",
|
196
|
+
expected_partial, @partials.keys)
|
197
|
+
assert(@partials.keys.any? {|l| l =~ expected_partial }, msg)
|
198
|
+
|
199
|
+
key = @partials.keys.find {|l| l =~ expected_partial }
|
200
|
+
value = @partials[key]
|
201
|
+
|
202
|
+
if expected_count = options[:count]
|
203
|
+
actual_count = value[:count]
|
204
|
+
msg = message || sprintf("expecting %s to be rendered %s time(s) but rendered %s time(s)",
|
205
|
+
expected_partial, expected_count, actual_count)
|
206
|
+
assert_equal expected_count, actual_count, msg
|
207
|
+
end
|
208
|
+
|
209
|
+
if expected_format = options[:format]
|
210
|
+
actual_format = value[:format]
|
211
|
+
msg = message || sprintf("expecting %s to be rendered as %s but rendered as %s",
|
212
|
+
expected_partial, expected_format, actual_format)
|
213
|
+
assert_equal expected_format, actual_format, msg
|
214
|
+
end
|
215
|
+
|
216
|
+
if expected_handler = options[:handler]
|
217
|
+
actual_handler = value[:handler]
|
218
|
+
msg = message || sprintf("expecting %s to be rendered as %s but rendered as %s",
|
219
|
+
expected_partial, expected_handler, actual_handler)
|
220
|
+
assert_equal expected_handler, actual_handler, msg
|
221
|
+
end
|
222
|
+
when nil, false
|
223
|
+
assert(@partials.empty?, msg)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
class ActionController::TestCase
|
231
|
+
|
232
|
+
def assigns(key = nil)
|
233
|
+
assigns = {}.with_indifferent_access
|
234
|
+
@controller.view_assigns.each { |k, v| assigns.regular_writer(k, v) }
|
235
|
+
key.nil? ? assigns : assigns[key]
|
236
|
+
end
|
237
|
+
|
238
|
+
end
|