hanami 2.1.0.beta1 → 2.1.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -4
  3. data/README.md +1 -1
  4. data/lib/hanami/app.rb +5 -0
  5. data/lib/hanami/config/actions.rb +4 -7
  6. data/lib/hanami/config/assets.rb +84 -0
  7. data/lib/hanami/config/null_config.rb +3 -0
  8. data/lib/hanami/config.rb +17 -5
  9. data/lib/hanami/extensions/action.rb +4 -2
  10. data/lib/hanami/extensions/view/standard_helpers.rb +4 -0
  11. data/lib/hanami/helpers/assets_helper.rb +752 -0
  12. data/lib/hanami/middleware/assets.rb +21 -0
  13. data/lib/hanami/middleware/render_errors.rb +4 -7
  14. data/lib/hanami/providers/assets.rb +44 -0
  15. data/lib/hanami/rake_tasks.rb +19 -18
  16. data/lib/hanami/settings.rb +1 -1
  17. data/lib/hanami/slice.rb +25 -4
  18. data/lib/hanami/version.rb +1 -1
  19. data/lib/hanami.rb +2 -2
  20. data/spec/integration/assets/assets_spec.rb +101 -0
  21. data/spec/integration/assets/serve_static_assets_spec.rb +152 -0
  22. data/spec/integration/logging/exception_logging_spec.rb +115 -0
  23. data/spec/integration/logging/notifications_spec.rb +68 -0
  24. data/spec/integration/logging/request_logging_spec.rb +128 -0
  25. data/spec/integration/rack_app/middleware_spec.rb +4 -4
  26. data/spec/integration/rack_app/rack_app_spec.rb +0 -221
  27. data/spec/integration/rake_tasks_spec.rb +107 -0
  28. data/spec/integration/view/context/assets_spec.rb +3 -9
  29. data/spec/integration/web/render_detailed_errors_spec.rb +17 -0
  30. data/spec/integration/web/render_errors_spec.rb +6 -4
  31. data/spec/support/app_integration.rb +46 -2
  32. data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +24 -36
  33. data/spec/unit/hanami/config/actions/csrf_protection_spec.rb +4 -3
  34. data/spec/unit/hanami/config/actions/default_values_spec.rb +3 -2
  35. data/spec/unit/hanami/env_spec.rb +11 -25
  36. data/spec/unit/hanami/helpers/assets_helper/asset_url_spec.rb +109 -0
  37. data/spec/unit/hanami/helpers/assets_helper/audio_tag_spec.rb +132 -0
  38. data/spec/unit/hanami/helpers/assets_helper/favicon_link_tag_spec.rb +91 -0
  39. data/spec/unit/hanami/helpers/assets_helper/image_tag_spec.rb +92 -0
  40. data/spec/unit/hanami/helpers/assets_helper/javascript_tag_spec.rb +143 -0
  41. data/spec/unit/hanami/helpers/assets_helper/stylesheet_link_tag_spec.rb +126 -0
  42. data/spec/unit/hanami/helpers/assets_helper/video_tag_spec.rb +132 -0
  43. data/spec/unit/hanami/version_spec.rb +1 -1
  44. metadata +32 -4
  45. data/lib/hanami/assets/app_config.rb +0 -61
  46. data/lib/hanami/assets/config.rb +0 -53
@@ -0,0 +1,128 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "rack/test"
5
+ require "stringio"
6
+
7
+ RSpec.describe "Logging / Request logging", :app_integration do
8
+ include Rack::Test::Methods
9
+
10
+ let(:app) { Hanami.app }
11
+
12
+ let(:logger_stream) { StringIO.new }
13
+
14
+ def configure_logger
15
+ Hanami.app.config.logger.stream = logger_stream
16
+ end
17
+
18
+ def logs
19
+ @logs ||= (logger_stream.rewind and logger_stream.read)
20
+ end
21
+
22
+ before do
23
+ with_directory(make_tmp_directory) do
24
+ write "config/app.rb", <<~RUBY
25
+ module TestApp
26
+ class App < Hanami::App
27
+ end
28
+ end
29
+ RUBY
30
+
31
+ require "hanami/setup"
32
+ configure_logger
33
+
34
+ before_prepare if respond_to?(:before_prepare)
35
+ require "hanami/prepare"
36
+ end
37
+ end
38
+
39
+ describe "app router" do
40
+ def before_prepare
41
+ write "config/routes.rb", <<~RUBY
42
+ module TestApp
43
+ class Routes < Hanami::Routes
44
+ root to: ->(env) { [200, {}, ["OK"]] }
45
+ end
46
+ end
47
+ RUBY
48
+ end
49
+
50
+ it "logs the requests" do
51
+ get "/"
52
+
53
+ expect(logs.split("\n").length).to eq 1
54
+ expect(logs).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
55
+ end
56
+
57
+ context "production env" do
58
+ around do |example|
59
+ @prev_hanami_env = ENV["HANAMI_ENV"]
60
+ ENV["HANAMI_ENV"] = "production"
61
+ example.run
62
+ ensure
63
+ ENV["HANAMI_ENV"] = @prev_hanami_env
64
+ end
65
+
66
+ it "logs the requests as JSON" do
67
+ get "/"
68
+
69
+ expect(logs.split("\n").length).to eq 1
70
+
71
+ json = JSON.parse(logs, symbolize_names: true)
72
+ expect(json).to include(
73
+ verb: "GET",
74
+ path: "/",
75
+ ip: "127.0.0.1",
76
+ elapsed: Integer,
77
+ elapsed_unit: a_string_matching(/(µs|ms)/),
78
+ )
79
+ end
80
+ end
81
+ end
82
+
83
+ describe "slice router" do
84
+ let(:app) { Main::Slice.rack_app }
85
+
86
+ def before_prepare
87
+ write "slices/main/config/routes.rb", <<~RUBY
88
+ module Main
89
+ class Routes < Hanami::Routes
90
+ root to: ->(env) { [200, {}, ["OK"]] }
91
+ end
92
+ end
93
+ RUBY
94
+ end
95
+
96
+ it "logs the requests" do
97
+ get "/"
98
+
99
+ expect(logs.split("\n").length).to eq 1
100
+ expect(logs).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
101
+ end
102
+
103
+ context "production env" do
104
+ around do |example|
105
+ @prev_hanami_env = ENV["HANAMI_ENV"]
106
+ ENV["HANAMI_ENV"] = "production"
107
+ example.run
108
+ ensure
109
+ ENV["HANAMI_ENV"] = @prev_hanami_env
110
+ end
111
+
112
+ it "logs the requests as JSON" do
113
+ get "/"
114
+
115
+ expect(logs.split("\n").length).to eq 1
116
+
117
+ json = JSON.parse(logs, symbolize_names: true)
118
+ expect(json).to include(
119
+ verb: "GET",
120
+ path: "/",
121
+ ip: "127.0.0.1",
122
+ elapsed: Integer,
123
+ elapsed_unit: a_string_matching(/(µs|ms)/),
124
+ )
125
+ end
126
+ end
127
+ end
128
+ end
@@ -317,7 +317,7 @@ RSpec.describe "Hanami web app", :app_integration do
317
317
  it "excludes not found routes in root scope" do
318
318
  get "/foo"
319
319
 
320
- expect(last_response.status).to eq 500
320
+ expect(last_response.status).to eq 404
321
321
  expect(last_response.headers).to_not have_key("X-Auth-User-ID")
322
322
  end
323
323
 
@@ -333,7 +333,7 @@ RSpec.describe "Hanami web app", :app_integration do
333
333
  it "does not uses the Rack middleware for not found paths" do
334
334
  get "/admin/users"
335
335
 
336
- expect(last_response.status).to eq 500
336
+ expect(last_response.status).to eq 404
337
337
  expect(last_response.headers).not_to have_key("X-Auth-User-ID")
338
338
  end
339
339
  end
@@ -600,7 +600,7 @@ RSpec.describe "Hanami web app", :app_integration do
600
600
  it "does not use Rack middleware for other paths" do
601
601
  get "/__not_found__"
602
602
 
603
- expect(last_response.status).to eq 500
603
+ expect(last_response.status).to eq 404
604
604
  expect(last_response.headers).not_to have_key("X-Identifier-Root")
605
605
  expect(last_response.headers).not_to have_key("X-Elapsed")
606
606
  expect(last_response.headers).not_to have_key("X-Auth-User-ID")
@@ -623,7 +623,7 @@ RSpec.describe "Hanami web app", :app_integration do
623
623
  it "uses Rack middleware for other paths" do
624
624
  get "/admin/__not_found__"
625
625
 
626
- expect(last_response.status).to eq 500
626
+ expect(last_response.status).to eq 404
627
627
  expect(last_response.headers).not_to have_key("X-Identifier-Admin")
628
628
  expect(last_response.headers).not_to have_key("X-Elapsed")
629
629
  expect(last_response.headers).not_to have_key("X-Elapsed")
@@ -33,227 +33,6 @@ RSpec.describe "Hanami web app", :app_integration do
33
33
  end
34
34
  end
35
35
 
36
- specify "Has rack monitor preconfigured with default request logging" do
37
- dir = Dir.mktmpdir
38
-
39
- with_tmp_directory(dir) do
40
- write "config/app.rb", <<~RUBY
41
- require "hanami"
42
-
43
- module TestApp
44
- class App < Hanami::App
45
- config.actions.format :json
46
- config.logger.options = {colorize: true}
47
- config.logger.stream = config.root.join("test.log")
48
- end
49
- end
50
- RUBY
51
-
52
- write "app/actions/users/index.rb", <<~RUBY
53
- module TestApp
54
- module Actions
55
- module Users
56
- class Index < Hanami::Action
57
- def handle(req, _resp)
58
- raise StandardError, "OH NOEZ"
59
- end
60
- end
61
- end
62
- end
63
- end
64
- RUBY
65
-
66
- write "app/actions/users/create.rb", <<~RUBY
67
- module TestApp
68
- module Actions
69
- module Users
70
- class Create < Hanami::Action
71
- def handle(req, resp)
72
- resp.body = req.params.to_h.keys
73
- end
74
- end
75
- end
76
- end
77
- end
78
- RUBY
79
-
80
- write "config/routes.rb", <<~RUBY
81
- module TestApp
82
- class Routes < Hanami::Routes
83
- root to: ->(env) { [200, {}, ["OK"]] }
84
- get "/users", to: "users.index"
85
- post "/users", to: "users.create"
86
- end
87
- end
88
- RUBY
89
-
90
- require "hanami/prepare"
91
-
92
- expect(Hanami.app["rack.monitor"]).to be_instance_of(Dry::Monitor::Rack::Middleware)
93
-
94
- get "/"
95
-
96
- logs = -> { Pathname(dir).join("test.log").realpath.read }
97
-
98
- expect(logs.()).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
99
-
100
- post "/users", JSON.generate(name: "jane", password: "secret"), {"CONTENT_TYPE" => "application/json"}
101
-
102
- expect(logs.()).to match %r{POST 200 \d+(µs|ms) 127.0.0.1 /}
103
-
104
- begin
105
- get "/users"
106
- rescue => e # rubocop:disable Style/RescueStandardError
107
- raise unless e.to_s == "OH NOEZ"
108
- end
109
-
110
- err_log = logs.()
111
-
112
- expect(err_log).to include("OH NOEZ")
113
- expect(err_log).to include("app/actions/users/index.rb:6:in `handle'")
114
- end
115
- end
116
-
117
- specify "Logging via the rack monitor even when notifications bus has already been used" do
118
- dir = Dir.mktmpdir
119
-
120
- with_tmp_directory(dir) do
121
- write "config/app.rb", <<~RUBY
122
- require "hanami"
123
-
124
- module TestApp
125
- class App < Hanami::App
126
- config.actions.format :json
127
- config.logger.options = {colorize: true}
128
- config.logger.stream = config.root.join("test.log")
129
- end
130
- end
131
- RUBY
132
-
133
- write "config/routes.rb", <<~RUBY
134
- module TestApp
135
- class Routes < Hanami::Routes
136
- post "/users", to: "users.create"
137
- end
138
- end
139
- RUBY
140
-
141
- write "app/actions/users/create.rb", <<~RUBY
142
- module TestApp
143
- module Actions
144
- module Users
145
- class Create < Hanami::Action
146
- def handle(req, resp)
147
- resp.body = req.params.to_h.keys
148
- end
149
- end
150
- end
151
- end
152
- end
153
- RUBY
154
-
155
- require "hanami/prepare"
156
-
157
- # Simulate any component interacting with the notifications bus such that it creates its
158
- # internal bus with a duplicate copy of all currently registered events. This means that the
159
- # class-level Dry::Monitor::Notification events implicitly registered by the
160
- # Dry::Monitor::Rack::Middleware activated via the rack provider are ignored, unless our
161
- # provider explicitly re-registers them on _instance_ of the notifications bus.
162
- #
163
- # See Hanami::Providers::Rack for more detail.
164
- Hanami.app["notifications"].instrument(:sql)
165
-
166
- logs = -> { Pathname(dir).join("test.log").realpath.read }
167
-
168
- post "/users", JSON.generate(name: "jane", password: "secret"), {"CONTENT_TYPE" => "application/json"}
169
- expect(logs.()).to match %r{POST 200 \d+(µs|ms) 127.0.0.1 /}
170
- end
171
- end
172
-
173
- describe "Request logging when using slice router" do
174
- let(:app) { Main::Slice.rack_app }
175
-
176
- specify "Has rack monitor preconfigured with default request logging (when used via a slice)" do
177
- dir = Dir.mktmpdir
178
-
179
- with_tmp_directory(dir) do
180
- write "config/app.rb", <<~RUBY
181
- require "hanami"
182
-
183
- module TestApp
184
- class App < Hanami::App
185
- config.logger.stream = config.root.join("test.log")
186
- end
187
- end
188
- RUBY
189
-
190
- write "slices/main/config/routes.rb", <<~RUBY
191
- module Main
192
- class Routes < Hanami::Routes
193
- root to: ->(env) { [200, {}, ["OK"]] }
194
- end
195
- end
196
- RUBY
197
-
198
- require "hanami/prepare"
199
-
200
- get "/"
201
-
202
- logs = -> { Pathname(dir).join("test.log").realpath.read }
203
-
204
- expect(logs.()).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
205
- end
206
- end
207
- end
208
-
209
- describe "Request logging on production" do
210
- let(:app) { Main::Slice.rack_app }
211
-
212
- around do |example|
213
- @prev_hanami_env = ENV["HANAMI_ENV"]
214
- ENV["HANAMI_ENV"] = "production"
215
- example.run
216
- ensure
217
- ENV["HANAMI_ENV"] = @prev_hanami_env
218
- end
219
-
220
- specify "Has rack monitor preconfigured with default request logging (when used via a slice)" do
221
- dir = Dir.mktmpdir
222
-
223
- with_tmp_directory(dir) do
224
- write "config/app.rb", <<~RUBY
225
- require "hanami"
226
-
227
- module TestApp
228
- class App < Hanami::App
229
- config.logger.stream = config.root.join("test.log")
230
- end
231
- end
232
- RUBY
233
-
234
- write "slices/main/config/routes.rb", <<~RUBY
235
- module Main
236
- class Routes < Hanami::Routes
237
- root to: ->(env) { [200, {}, ["OK"]] }
238
- end
239
- end
240
- RUBY
241
-
242
- require "hanami/boot"
243
-
244
- get "/"
245
-
246
- logs = -> { Pathname(dir).join("test.log").realpath.read }
247
-
248
- log_content = logs.()
249
-
250
- expect(log_content).to match(%r["verb":"GET"])
251
- expect(log_content).to match(%r["path":"/"])
252
- expect(log_content).to match(%r[elapsed":\d+,"elapsed_unit":"µs"])
253
- end
254
- end
255
- end
256
-
257
36
  specify "Routing to actions based on their container identifiers" do
258
37
  with_tmp_directory(Dir.mktmpdir) do
259
38
  write "config/app.rb", <<~RUBY
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rake"
4
+ require "hanami/cli/bundler"
5
+
6
+ RSpec.describe "Rake tasks", :app_integration do
7
+ describe "assets:precompile" do
8
+ before do
9
+ allow(Hanami).to receive(:bundled?)
10
+ allow(Hanami).to receive(:bundled?).with("hanami-assets").and_return(hanami_assets_bundled)
11
+ end
12
+
13
+ context "when hanami-assets is bundled" do
14
+ let(:hanami_assets_bundled) { true }
15
+
16
+ xit "compiles assets" do
17
+ with_tmp_directory(Dir.mktmpdir) do
18
+ write "config/app.rb", <<~'RUBY'
19
+ require "hanami"
20
+
21
+ module TestApp
22
+ class App < Hanami::App
23
+ end
24
+ end
25
+ RUBY
26
+
27
+ write "Rakefile", <<~RUBY
28
+ # frozen_string_literal: true
29
+
30
+ require "hanami/rake_tasks"
31
+ RUBY
32
+
33
+ write "app/assets/js/app.js", <<~JS
34
+ console.log("Hello from index.js");
35
+ JS
36
+
37
+ before_prepare if respond_to?(:before_prepare)
38
+ require "hanami/prepare"
39
+
40
+ expect_any_instance_of(Hanami::CLI::Bundler).to receive(:hanami_exec).with("assets compile").and_return(true)
41
+
42
+ Rake::Task["assets:precompile"].invoke
43
+ end
44
+ end
45
+
46
+ it "doesn't list the task" do
47
+ with_tmp_directory(Dir.mktmpdir) do
48
+ write "config/app.rb", <<~'RUBY'
49
+ require "hanami"
50
+
51
+ module TestApp
52
+ class App < Hanami::App
53
+ end
54
+ end
55
+ RUBY
56
+
57
+ write "Rakefile", <<~RUBY
58
+ # frozen_string_literal: true
59
+
60
+ require "hanami/rake_tasks"
61
+ RUBY
62
+
63
+ before_prepare if respond_to?(:before_prepare)
64
+ require "hanami/prepare"
65
+
66
+ output = `bundle exec rake -T`
67
+ expect(output).to_not include("assets:precompile")
68
+ end
69
+ end
70
+ end
71
+
72
+ context "when hanami-assets is not bundled" do
73
+ let(:hanami_assets_bundled) { false }
74
+
75
+ it "raises error" do
76
+ with_tmp_directory(Dir.mktmpdir) do
77
+ write "config/app.rb", <<~'RUBY'
78
+ require "hanami"
79
+
80
+ module TestApp
81
+ class App < Hanami::App
82
+ end
83
+ end
84
+ RUBY
85
+
86
+ write "Rakefile", <<~RUBY
87
+ # frozen_string_literal: true
88
+
89
+ require "hanami/rake_tasks"
90
+ RUBY
91
+
92
+ write "app/assets/js/app.js", <<~JS
93
+ console.log("Hello from index.js");
94
+ JS
95
+
96
+ before_prepare if respond_to?(:before_prepare)
97
+ require "hanami/prepare"
98
+
99
+ expect { Rake::Task["assets:precompile"].invoke }.to raise_error do |exception|
100
+ expect(exception).to be_a(RuntimeError)
101
+ expect(exception.message).to match(/Don't know how to build task 'assets:precompile'/)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -24,21 +24,15 @@ RSpec.describe "App view / Context / Assets", :app_integration do
24
24
 
25
25
  describe "#assets" do
26
26
  context "without assets provider" do
27
- it "raises error" do
27
+ xit "raises error" do
28
+ allow(Hanami).to receive(:bundled?).with("hanami-assets").and_return(false)
29
+
28
30
  expect { context.assets }
29
31
  .to raise_error(Hanami::ComponentLoadError, /hanami-assets/)
30
32
  end
31
33
  end
32
34
 
33
35
  context "with assets provider" do
34
- before do
35
- Hanami.app.register_provider(:assets) do
36
- start do
37
- register "assets", Object.new
38
- end
39
- end
40
- end
41
-
42
36
  it "is the app assets by default" do
43
37
  expect(context.assets).to be TestApp::App[:assets]
44
38
  end
@@ -56,6 +56,15 @@ RSpec.describe "Web / Rendering detailed errors", :app_integration do
56
56
  expect(html).to have_selector("header", text: "RuntimeError at /error")
57
57
  expect(html).to have_selector("ul.frames li.application", text: "app/actions/error.rb")
58
58
  end
59
+
60
+ it "renders a detailed HTML error page and returns a 404 status for a not found error" do
61
+ get "/__not_found__", {}, "HTTP_ACCEPT" => "text/html"
62
+
63
+ expect(last_response.status).to eq 404
64
+
65
+ html = Capybara.string(last_response.body)
66
+ expect(html).to have_selector("header", text: "Hanami::Router::NotFoundError at /__not_found__")
67
+ end
59
68
  end
60
69
 
61
70
  describe "Other request types" do
@@ -67,6 +76,14 @@ RSpec.describe "Web / Rendering detailed errors", :app_integration do
67
76
  expect(last_response.body).to include "RuntimeError at /error"
68
77
  expect(last_response.body).to match %r{App backtrace.+app/actions/error.rb}m
69
78
  end
79
+
80
+ it "renders a detailed error page in text and returns a 404 status for a not found error" do
81
+ get "/__not_found__", {}, "HTTP_ACCEPT" => "text/html"
82
+
83
+ expect(last_response.status).to eq 404
84
+
85
+ expect(last_response.body).to include "Hanami::Router::NotFoundError at /__not_found__"
86
+ end
70
87
  end
71
88
 
72
89
  describe "render_detailed_errors config disabled" do
@@ -225,12 +225,14 @@ RSpec.describe "Web / Rendering errors", :app_integration do
225
225
  HTML
226
226
  end
227
227
 
228
- it "raises a Hanami::Router::NotFoundError for a 404" do
229
- expect { get "/__not_found__" }.to raise_error(Hanami::Router::NotFoundError)
228
+ it "renders the hanami-router default 404 response for a not found error" do
229
+ get "/__not_found__"
230
+ expect(last_response.status).to eq 404
230
231
  end
231
232
 
232
- it "raises a Hanami::Router::NotAllowedError for a 405" do
233
- expect { post "/index" }.to raise_error(Hanami::Router::NotAllowedError)
233
+ it "renders the hanami-router default 405 response for a not allowed error" do
234
+ post "/index"
235
+ expect(last_response.status).to eq 405
234
236
  end
235
237
 
236
238
  it "raises the original error for a 500" do
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "hanami/devtools/integration/files"
4
4
  require "hanami/devtools/integration/with_tmp_directory"
5
+ require "json"
5
6
  require "tmpdir"
6
7
  require "zeitwerk"
7
8
 
@@ -16,10 +17,52 @@ module RSpec
16
17
  end
17
18
  end
18
19
  end
20
+
21
+ module App
22
+ def self.included(base)
23
+ super
24
+
25
+ base.class_eval do
26
+ let!(:node_modules_path) { File.join(Dir.pwd, "node_modules") }
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def stub_assets(*assets)
33
+ manifest_hash = assets.each_with_object({}) { |source_path, hsh|
34
+ hsh[source_path] = {url: File.join("/assets", source_path)}
35
+ }
36
+
37
+ write "public/assets.json", JSON.generate(manifest_hash)
38
+ end
39
+
40
+ def compile_assets!
41
+ link_node_modules
42
+
43
+ require "hanami/cli/command"
44
+ require "hanami/cli/commands/app/command"
45
+ require "hanami/cli/commands/app/assets/compile"
46
+ compiler = Hanami::CLI::Commands::App::Assets::Compile.new(config: Hanami.app.config.assets)
47
+
48
+ with_directory(Hanami.app.root) do
49
+ compiler.call
50
+ end
51
+ end
52
+
53
+ def link_node_modules
54
+ root = Hanami.app.root
55
+
56
+ return if File.exist?(File.join(root, "node_modules", "hanami-assets", "dist", "hanami-assets.js"))
57
+
58
+ FileUtils.ln_s(node_modules_path, root)
59
+ rescue Errno::EEXIST # rubocop:disable Lint/SuppressedException
60
+ end
61
+ end
19
62
  end
20
63
  end
21
64
 
22
- RSpec.shared_context "Application integration" do
65
+ RSpec.shared_context "App integration" do
23
66
  let(:app_modules) { %i[TestApp Admin Main Search] }
24
67
  end
25
68
 
@@ -35,7 +78,8 @@ end
35
78
  RSpec.configure do |config|
36
79
  config.include RSpec::Support::Files, :app_integration
37
80
  config.include RSpec::Support::WithTmpDirectory, :app_integration
38
- config.include_context "Application integration", :app_integration
81
+ config.include RSpec::Support::App, :app_integration
82
+ config.include_context "App integration", :app_integration
39
83
 
40
84
  config.before :each, :app_integration do
41
85
  # Conditionally assign these in case they have been assigned earlier for specific