aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/test/actionpack/abstract/abstract_controller_test.rb
blob: 8f65a61493314b98ac0a9e94ba79609d92520a40 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
require "abstract_unit"
require "set"

module AbstractController
  module Testing
    # Test basic dispatching.
    # ====
    # * Call process
    # * Test that the response_body is set correctly
    class SimpleController < AbstractController::Base
    end

    class Me < SimpleController
      def index
        self.response_body = "Hello world"
        "Something else"
      end
    end

    class TestBasic < ActiveSupport::TestCase
      test "dispatching works" do
        controller = Me.new
        controller.process(:index)
        assert_equal "Hello world", controller.response_body
      end
    end

    # Test Render mixin
    # ====
    class RenderingController < AbstractController::Base
      include AbstractController::Rendering
      include ActionView::Rendering

      def _prefixes
        []
      end

      def render(options = {})
        if options.is_a?(String)
          options = { _template_name: options }
        end
        super
      end

      append_view_path File.expand_path("views", __dir__)
    end

    class Me2 < RenderingController
      def index
        render "index.erb"
      end

      def index_to_string
        self.response_body = render_to_string "index"
      end

      def action_with_ivars
        @my_ivar = "Hello"
        render "action_with_ivars.erb"
      end

      def naked_render
        render
      end

      def rendering_to_body
        self.response_body = render_to_body template: "naked_render"
      end

      def rendering_to_string
        self.response_body = render_to_string template: "naked_render"
      end
    end

    class TestRenderingController < ActiveSupport::TestCase
      def setup
        @controller = Me2.new
      end

      test "rendering templates works" do
        @controller.process(:index)
        assert_equal "Hello from index.erb", @controller.response_body
      end

      test "render_to_string works with a String as an argument" do
        @controller.process(:index_to_string)
        assert_equal "Hello from index.erb", @controller.response_body
      end

      test "rendering passes ivars to the view" do
        @controller.process(:action_with_ivars)
        assert_equal "Hello from index_with_ivars.erb", @controller.response_body
      end

      test "rendering with no template name" do
        @controller.process(:naked_render)
        assert_equal "Hello from naked_render.erb", @controller.response_body
      end

      test "rendering to a rack body" do
        @controller.process(:rendering_to_body)
        assert_equal "Hello from naked_render.erb", @controller.response_body
      end

      test "rendering to a string" do
        @controller.process(:rendering_to_string)
        assert_equal "Hello from naked_render.erb", @controller.response_body
      end
    end

    # Test rendering with prefixes
    # ====
    # * self._prefix is used when defined
    class PrefixedViews < RenderingController
      private
        def self.prefix
          name.underscore
        end

        def _prefixes
          [self.class.prefix]
        end
    end

    class Me3 < PrefixedViews
      def index
        render
      end

      def formatted
        self.formats = [:html]
        render
      end
    end

    class TestPrefixedViews < ActiveSupport::TestCase
      def setup
        @controller = Me3.new
      end

      test "templates are located inside their 'prefix' folder" do
        @controller.process(:index)
        assert_equal "Hello from me3/index.erb", @controller.response_body
      end

      test "templates included their format" do
        @controller.process(:formatted)
        assert_equal "Hello from me3/formatted.html.erb", @controller.response_body
      end
    end

    class OverridingLocalPrefixes < AbstractController::Base
      include AbstractController::Rendering
      include ActionView::Rendering
      append_view_path File.expand_path("views", __dir__)

      def index
        render
      end

      def self.local_prefixes
        # this would usually return "abstract_controller/testing/overriding_local_prefixes"
        super + ["abstract_controller/testing/me3"]
      end

      class Inheriting < self
      end
    end

    class OverridingLocalPrefixesTest < ActiveSupport::TestCase
      test "overriding .local_prefixes adds prefix" do
        @controller = OverridingLocalPrefixes.new
        @controller.process(:index)
        assert_equal "Hello from me3/index.erb", @controller.response_body
      end

      test ".local_prefixes is inherited" do
        @controller = OverridingLocalPrefixes::Inheriting.new
        @controller.process(:index)
        assert_equal "Hello from me3/index.erb", @controller.response_body
      end
    end

    # Test rendering with layouts
    # ====
    # self._layout is used when defined
    class WithLayouts < PrefixedViews
      include ActionView::Layouts

      private
        def self.layout(formats)
          find_template(name.underscore, { formats: formats }, _prefixes: ["layouts"])
        rescue ActionView::MissingTemplate
          begin
            find_template("application", { formats: formats }, _prefixes: ["layouts"])
          rescue ActionView::MissingTemplate
          end
        end

        def render_to_body(options = {})
          options[:_layout] = options[:layout] || _default_layout({})
          super
        end
    end

    class Me4 < WithLayouts
      def index
        render
      end
    end

    class TestLayouts < ActiveSupport::TestCase
      test "layouts are included" do
        controller = Me4.new
        controller.process(:index)
        assert_equal "Me4 Enter : Hello from me4/index.erb : Exit", controller.response_body
      end
    end

    # respond_to_action?(action_name)
    # ====
    # * A method can be used as an action only if this method
    #   returns true when passed the method name as an argument
    # * Defaults to true in AbstractController
    class DefaultRespondToActionController < AbstractController::Base
      def index() self.response_body = "success" end
    end

    class ActionMissingRespondToActionController < AbstractController::Base
    # No actions
    private
      def action_missing(action_name)
        self.response_body = "success"
      end
    end

    class RespondToActionController < AbstractController::Base;
      def index() self.response_body = "success" end

      def fail()  self.response_body = "fail"    end

    private

      def method_for_action(action_name)
        action_name.to_s != "fail" && action_name
      end
    end

    class TestRespondToAction < ActiveSupport::TestCase
      def assert_dispatch(klass, body = "success", action = :index)
        controller = klass.new
        controller.process(action)
        assert_equal body, controller.response_body
      end

      test "an arbitrary method is available as an action by default" do
        assert_dispatch DefaultRespondToActionController, "success", :index
      end

      test "raises ActionNotFound when method does not exist and action_missing is not defined" do
        assert_raise(ActionNotFound) { DefaultRespondToActionController.new.process(:fail) }
      end

      test "dispatches to action_missing when method does not exist and action_missing is defined" do
        assert_dispatch ActionMissingRespondToActionController, "success", :ohai
      end

      test "a method is available as an action if method_for_action returns true" do
        assert_dispatch RespondToActionController, "success", :index
      end

      test "raises ActionNotFound if method is defined but method_for_action returns false" do
        assert_raise(ActionNotFound) { RespondToActionController.new.process(:fail) }
      end
    end

    class Me6 < AbstractController::Base
      action_methods

      def index
      end
    end

    class TestActionMethodsReloading < ActiveSupport::TestCase
      test "action_methods should be reloaded after defining a new method" do
        assert_equal Set.new(["index"]), Me6.action_methods
      end
    end
  end
end