Skip to content

Commit 82e33e4

Browse files
authored
Merge pull request rails#49819 from gmcgibbon/integration_with_routes
Make with_routing test helper work for integration tests
2 parents 04f29cb + d46d5ce commit 82e33e4

File tree

13 files changed

+258
-110
lines changed

13 files changed

+258
-110
lines changed

actionpack/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
* Add support for `with_routing` test helper in `ActionDispatch::IntegrationTest`
2+
3+
*Gannon McGibbon*
4+
15
* Remove deprecated support to set `Rails.application.config.action_dispatch.show_exceptions` to `true` and `false`.
26

37
*Rafael Mendonça França*

actionpack/lib/action_dispatch/testing/assertions/routing.rb

Lines changed: 79 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,65 @@ module Assertions
1111
module RoutingAssertions
1212
extend ActiveSupport::Concern
1313

14+
module WithIntegrationRouting # :nodoc:
15+
extend ActiveSupport::Concern
16+
17+
module ClassMethods
18+
def with_routing(&block)
19+
old_routes = nil
20+
old_integration_session = nil
21+
22+
setup do
23+
old_routes = app.routes
24+
old_integration_session = integration_session
25+
create_routes(&block)
26+
end
27+
28+
teardown do
29+
reset_routes(old_routes, old_integration_session)
30+
end
31+
end
32+
end
33+
34+
def with_routing(&block)
35+
old_routes = app.routes
36+
old_integration_session = integration_session
37+
create_routes(&block)
38+
ensure
39+
reset_routes(old_routes, old_integration_session)
40+
end
41+
42+
private
43+
def create_routes
44+
app = self.app
45+
routes = ActionDispatch::Routing::RouteSet.new
46+
rack_app = app.config.middleware.build(routes)
47+
https = integration_session.https?
48+
host = integration_session.host
49+
50+
app.instance_variable_set(:@routes, routes)
51+
app.instance_variable_set(:@app, rack_app)
52+
@integration_session = Class.new(ActionDispatch::Integration::Session) do
53+
include app.routes.url_helpers
54+
include app.routes.mounted_helpers
55+
end.new(app)
56+
@integration_session.https! https
57+
@integration_session.host! host
58+
@routes = routes
59+
60+
yield routes
61+
end
62+
63+
def reset_routes(old_routes, old_integration_session)
64+
old_rack_app = app.config.middleware.build(old_routes)
65+
66+
app.instance_variable_set(:@routes, old_routes)
67+
app.instance_variable_set(:@app, old_rack_app)
68+
@integration_session = old_integration_session
69+
@routes = old_routes
70+
end
71+
end
72+
1473
module ClassMethods
1574
# A helper to make it easier to test different route configurations.
1675
# This method temporarily replaces @routes with a new RouteSet instance
@@ -44,6 +103,26 @@ def setup # :nodoc:
44103
super
45104
end
46105

106+
# A helper to make it easier to test different route configurations.
107+
# This method temporarily replaces @routes with a new RouteSet instance.
108+
#
109+
# The new instance is yielded to the passed block. Typically the block
110+
# will create some routes using <tt>set.draw { match ... }</tt>:
111+
#
112+
# with_routing do |set|
113+
# set.draw do
114+
# resources :users
115+
# end
116+
# assert_equal "/users", users_path
117+
# end
118+
#
119+
def with_routing(&block)
120+
old_routes, old_controller = @routes, @controller
121+
create_routes(&block)
122+
ensure
123+
reset_routes(old_routes, old_controller)
124+
end
125+
47126
# Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash)
48127
# match +path+. Basically, it asserts that \Rails recognizes the route given by +expected_options+.
49128
#
@@ -167,26 +246,6 @@ def assert_routing(path, options, defaults = {}, extras = {}, message = nil)
167246
assert_generates(path.is_a?(Hash) ? path[:path] : path, generate_options, defaults, extras, message)
168247
end
169248

170-
# A helper to make it easier to test different route configurations.
171-
# This method temporarily replaces @routes with a new RouteSet instance.
172-
#
173-
# The new instance is yielded to the passed block. Typically the block
174-
# will create some routes using <tt>set.draw { match ... }</tt>:
175-
#
176-
# with_routing do |set|
177-
# set.draw do
178-
# resources :users
179-
# end
180-
# assert_equal "/users", users_path
181-
# end
182-
#
183-
def with_routing(&block)
184-
old_routes, old_controller = @routes, @controller
185-
create_routes(&block)
186-
ensure
187-
reset_routes(old_routes, old_controller)
188-
end
189-
190249
# ROUTES TODO: These assertions should really work in an integration context
191250
def method_missing(selector, *args, &block)
192251
if defined?(@controller) && @controller && defined?(@routes) && @routes && @routes.named_routes.route_defined?(selector)

actionpack/lib/action_dispatch/testing/integration.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,7 @@ module Behavior
657657
included do
658658
include ActionDispatch::Routing::UrlFor
659659
include UrlOptions # don't let UrlFor override the url_options method
660+
include ActionDispatch::Assertions::RoutingAssertions::WithIntegrationRouting
660661
ActiveSupport.run_load_hooks(:action_dispatch_integration_test, self)
661662
@@app = nil
662663
end

actionpack/test/abstract_unit.rb

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,23 @@ class TestCase
9191
end
9292

9393
class RoutedRackApp
94+
class Config < Struct.new(:middleware)
95+
end
96+
9497
attr_reader :routes
9598

9699
def initialize(routes, &blk)
97100
@routes = routes
98-
@stack = ActionDispatch::MiddlewareStack.new(&blk).build(@routes)
101+
@stack = ActionDispatch::MiddlewareStack.new(&blk)
102+
@app = @stack.build(@routes)
99103
end
100104

101105
def call(env)
102-
@stack.call(env)
106+
@app.call(env)
107+
end
108+
109+
def config
110+
Config.new(@stack)
103111
end
104112
end
105113

@@ -150,19 +158,6 @@ def self.stub_controllers(config = ActionDispatch::Routing::RouteSet::DEFAULT_CO
150158
yield DeadEndRoutes.new(config)
151159
end
152160

153-
def with_routing(&block)
154-
temporary_routes = ActionDispatch::Routing::RouteSet.new
155-
old_app, self.class.app = self.class.app, self.class.build_app(temporary_routes)
156-
old_routes = SharedTestRoutes
157-
silence_warnings { Object.const_set(:SharedTestRoutes, temporary_routes) }
158-
159-
yield temporary_routes
160-
ensure
161-
self.class.app = old_app
162-
remove!
163-
silence_warnings { Object.const_set(:SharedTestRoutes, old_routes) }
164-
end
165-
166161
def with_autoload_path(path)
167162
path = File.join(__dir__, "fixtures", path)
168163
Zeitwerk.with_loader do |loader|

actionpack/test/controller/flash_test.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,14 @@ def get(path, **options)
377377
super(path, **options)
378378
end
379379

380+
def app
381+
@app ||= self.class.build_app do |middleware|
382+
middleware.use ActionDispatch::Session::CookieStore, key: SessionKey
383+
middleware.use ActionDispatch::Flash
384+
middleware.delete ActionDispatch::ShowExceptions
385+
end
386+
end
387+
380388
def with_test_route_set
381389
with_routing do |set|
382390
set.draw do
@@ -385,12 +393,6 @@ def with_test_route_set
385393
end
386394
end
387395

388-
@app = self.class.build_app(set) do |middleware|
389-
middleware.use ActionDispatch::Session::CookieStore, key: SessionKey
390-
middleware.use ActionDispatch::Flash
391-
middleware.delete ActionDispatch::ShowExceptions
392-
end
393-
394396
yield
395397
end
396398
end

actionpack/test/controller/integration_test.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,17 @@ class RackLintIntegrationTest < ActionDispatch::IntegrationTest
172172
get "/", to: ->(_) { [200, {}, [""]] }
173173
end
174174

175-
@app = self.class.build_app(set) do |middleware|
176-
middleware.unshift Rack::Lint
177-
end
178-
179175
get "/"
180176

181177
assert_equal 200, status
182178
end
183179
end
180+
181+
def app
182+
@app ||= self.class.build_app do |middleware|
183+
middleware.unshift Rack::Lint
184+
end
185+
end
184186
end
185187

186188
# Tests that integration tests don't call Controller test methods for processing.

actionpack/test/dispatch/request/query_string_parsing_test.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,16 +157,19 @@ def test_array_parses_without_nil
157157
end
158158

159159
private
160+
def app
161+
@app ||= self.class.build_app do |middleware|
162+
middleware.use(EarlyParse)
163+
end
164+
end
165+
160166
def assert_parses(expected, actual)
161167
with_routing do |set|
162168
set.draw do
163169
ActionDispatch.deprecator.silence do
164170
get ":action", to: ::QueryStringParsingTest::TestController
165171
end
166172
end
167-
@app = self.class.build_app(set) do |middleware|
168-
middleware.use(EarlyParse)
169-
end
170173

171174
get "/parse", params: actual
172175
assert_response :ok

actionpack/test/dispatch/request_id_test.rb

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ def index
5555
end
5656
end
5757

58+
setup do
59+
@header = "X-Request-Id"
60+
end
61+
5862
test "request id is passed all the way to the response" do
5963
with_test_route_set do
6064
get "/"
@@ -70,25 +74,28 @@ def index
7074
end
7175

7276
test "using a custom request_id header key" do
73-
with_test_route_set(header: "X-Tracer-Id") do
77+
@header = "X-Tracer-Id"
78+
with_test_route_set do
7479
get "/"
7580
assert_match(/\w+/, @response.headers["X-Tracer-Id"])
7681
end
7782
end
7883

7984
private
85+
def app
86+
@app ||= self.class.build_app do |middleware|
87+
middleware.use Rack::Lint
88+
middleware.use ActionDispatch::RequestId, header: @header
89+
middleware.use Rack::Lint
90+
end
91+
end
92+
8093
def with_test_route_set(header: "X-Request-Id")
8194
with_routing do |set|
8295
set.draw do
8396
get "/", to: ::RequestIdResponseTest::TestController.action(:index)
8497
end
8598

86-
@app = self.class.build_app(set) do |middleware|
87-
middleware.use Rack::Lint
88-
middleware.use ActionDispatch::RequestId, header: header
89-
middleware.use Rack::Lint
90-
end
91-
9299
yield
93100
end
94101
end

0 commit comments

Comments
 (0)