hanami 2.2.1 → 2.3.0.beta1

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -1
  3. data/README.md +20 -35
  4. data/hanami.gemspec +3 -2
  5. data/lib/hanami/app.rb +2 -0
  6. data/lib/hanami/config/actions/content_security_policy.rb +23 -0
  7. data/lib/hanami/config/actions.rb +21 -0
  8. data/lib/hanami/config/console.rb +79 -0
  9. data/lib/hanami/config/logger.rb +1 -1
  10. data/lib/hanami/config.rb +13 -0
  11. data/lib/hanami/constants.rb +3 -0
  12. data/lib/hanami/extensions/db/repo.rb +11 -6
  13. data/lib/hanami/extensions/view/context.rb +10 -0
  14. data/lib/hanami/helpers/assets_helper.rb +92 -25
  15. data/lib/hanami/middleware/content_security_policy_nonce.rb +53 -0
  16. data/lib/hanami/slice.rb +22 -6
  17. data/lib/hanami/slice_registrar.rb +1 -1
  18. data/lib/hanami/version.rb +1 -1
  19. data/lib/hanami.rb +10 -2
  20. data/spec/integration/assets/cross_slice_assets_helpers_spec.rb +0 -1
  21. data/spec/integration/assets/serve_static_assets_spec.rb +1 -1
  22. data/spec/integration/container/autoloader_spec.rb +2 -0
  23. data/spec/integration/db/db_spec.rb +1 -1
  24. data/spec/integration/db/logging_spec.rb +63 -0
  25. data/spec/integration/db/repo_spec.rb +87 -2
  26. data/spec/integration/logging/exception_logging_spec.rb +6 -1
  27. data/spec/integration/rack_app/middleware_spec.rb +4 -11
  28. data/spec/integration/view/helpers/form_helper_spec.rb +1 -1
  29. data/spec/integration/web/content_security_policy_nonce_spec.rb +251 -0
  30. data/spec/support/app_integration.rb +2 -1
  31. data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +7 -0
  32. data/spec/unit/hanami/config/console_spec.rb +22 -0
  33. data/spec/unit/hanami/env_spec.rb +10 -13
  34. data/spec/unit/hanami/slice_spec.rb +18 -0
  35. data/spec/unit/hanami/version_spec.rb +1 -1
  36. data/spec/unit/hanami/web/rack_logger_spec.rb +11 -4
  37. metadata +27 -18
  38. data/spec/support/shared_examples/cli/generate/app.rb +0 -494
  39. data/spec/support/shared_examples/cli/generate/migration.rb +0 -32
  40. data/spec/support/shared_examples/cli/generate/model.rb +0 -81
  41. data/spec/support/shared_examples/cli/new.rb +0 -97
@@ -1,494 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/utils/string"
4
-
5
- RSpec.shared_examples "a new app" do
6
- let(:app) { Hanami::Utils::String.new(input).underscore.to_s }
7
-
8
- it "generates vanilla app" do
9
- project = "bookshelf_generate_app_#{Random.rand(100_000_000)}"
10
-
11
- with_project(project) do
12
- app_name = Hanami::Utils::String.new(app).classify
13
- app_upcase = Hanami::Utils::String.new(app).upcase
14
- output = <<-OUT
15
- create apps/#{app}/application.rb
16
- create apps/#{app}/config/routes.rb
17
- create apps/#{app}/views/application_layout.rb
18
- create apps/#{app}/templates/application.html.erb
19
- create apps/#{app}/assets/favicon.ico
20
- create apps/#{app}/controllers/.gitkeep
21
- create apps/#{app}/assets/images/.gitkeep
22
- create apps/#{app}/assets/javascripts/.gitkeep
23
- create apps/#{app}/assets/stylesheets/.gitkeep
24
- create spec/#{app}/features/.gitkeep
25
- create spec/#{app}/controllers/.gitkeep
26
- create spec/#{app}/views/application_layout_spec.rb
27
- insert config/environment.rb
28
- insert config/environment.rb
29
- append .env.development
30
- append .env.test
31
- OUT
32
-
33
- run_cmd "hanami generate app #{input}", output
34
-
35
- #
36
- # apps/<app>/application.rb
37
- #
38
- expect("apps/#{app}/application.rb").to have_file_content <<-END
39
- require 'hanami/helpers'
40
- require 'hanami/assets'
41
-
42
- module #{app_name}
43
- class App < Hanami::App
44
- configure do
45
- ##
46
- # BASIC
47
- #
48
-
49
- # Define the root path of this application.
50
- # All paths specified in this configuration are relative to path below.
51
- #
52
- root __dir__
53
-
54
- # Relative load paths where this application will recursively load the
55
- # code.
56
- #
57
- # When you add new directories, remember to add them here.
58
- #
59
- load_paths << [
60
- 'controllers',
61
- 'views'
62
- ]
63
-
64
- # Handle exceptions with HTTP statuses (true) or don't catch them (false).
65
- # Defaults to true.
66
- # See: http://www.rubydoc.info/gems/hanami-controller/#Exceptions_management
67
- #
68
- # handle_exceptions true
69
-
70
- ##
71
- # HTTP
72
- #
73
-
74
- # Routes definitions for this application
75
- # See: http://www.rubydoc.info/gems/hanami-router#Usage
76
- #
77
- routes 'config/routes'
78
-
79
- # URI scheme used by the routing system to generate absolute URLs
80
- # Defaults to "http"
81
- #
82
- # scheme 'https'
83
-
84
- # URI host used by the routing system to generate absolute URLs
85
- # Defaults to "localhost"
86
- #
87
- # host 'example.org'
88
-
89
- # URI port used by the routing system to generate absolute URLs
90
- # Argument: An object coercible to integer, defaults to 80 if the scheme
91
- # is http and 443 if it's https
92
- #
93
- # This should only be configured if app listens to non-standard ports
94
- #
95
- # port 443
96
-
97
- # Enable cookies
98
- # Argument: boolean to toggle the feature
99
- # A Hash with options
100
- #
101
- # Options:
102
- # :domain - The domain (String - nil by default, not required)
103
- # :path - Restrict cookies to a relative URI
104
- # (String - nil by default)
105
- # :max_age - Cookies expiration expressed in seconds
106
- # (Integer - nil by default)
107
- # :secure - Restrict cookies to secure connections
108
- # (Boolean - Automatically true when using HTTPS)
109
- # See #scheme and #ssl?
110
- # :httponly - Prevent JavaScript access (Boolean - true by default)
111
- #
112
- # cookies true
113
- # or
114
- # cookies max_age: 300
115
-
116
- # Enable sessions
117
- # Argument: Symbol the Rack session adapter
118
- # A Hash with options
119
- #
120
- # See: http://www.rubydoc.info/gems/rack/Rack/Session/Cookie
121
- #
122
- # sessions :cookie, secret: ENV['#{app_upcase}_SESSIONS_SECRET']
123
-
124
- # Configure Rack middleware for this application
125
- #
126
- # middleware.use Rack::Protection
127
-
128
- # Default format for the requests that don't specify an HTTP_ACCEPT header
129
- # Argument: A symbol representation of a mime type, defaults to :html
130
- #
131
- # default_request_format :html
132
-
133
- # Default format for responses that don't consider the request format
134
- # Argument: A symbol representation of a mime type, defaults to :html
135
- #
136
- # default_response_format :html
137
-
138
- ##
139
- # TEMPLATES
140
- #
141
-
142
- # The layout to be used by all views
143
- #
144
- layout :application # It will load #{app_name}::Views::ApplicationLayout
145
-
146
- # The relative path to templates
147
- #
148
- templates 'templates'
149
-
150
- ##
151
- # ASSETS
152
- #
153
- assets do
154
- # JavaScript compressor
155
- #
156
- # Supported engines:
157
- #
158
- # * :builtin
159
- # * :uglifier
160
- # * :yui
161
- # * :closure
162
- #
163
- # See: https://guides.hanamirb.org/assets/compressors
164
- #
165
- # In order to skip JavaScript compression comment the following line
166
- javascript_compressor :builtin
167
-
168
- # Stylesheet compressor
169
- #
170
- # Supported engines:
171
- #
172
- # * :builtin
173
- # * :yui
174
- # * :sass
175
- #
176
- # See: https://guides.hanamirb.org/assets/compressors
177
- #
178
- # In order to skip stylesheet compression comment the following line
179
- stylesheet_compressor :builtin
180
-
181
- # Specify sources for assets
182
- #
183
- sources << [
184
- 'assets'
185
- ]
186
- end
187
-
188
- ##
189
- # SECURITY
190
- #
191
-
192
- # X-Frame-Options is a HTTP header supported by modern browsers.
193
- # It determines if a web page can or cannot be included via <frame> and
194
- # <iframe> tags by untrusted domains.
195
- #
196
- # Web applications can send this header to prevent Clickjacking attacks.
197
- #
198
- # Read more at:
199
- #
200
- # * https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options
201
- # * https://www.owasp.org/index.php/Clickjacking
202
- #
203
- security.x_frame_options 'DENY'
204
-
205
- # X-Content-Type-Options prevents browsers from interpreting files as
206
- # something else than declared by the content type in the HTTP headers.
207
- #
208
- # Read more at:
209
- #
210
- # * https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#X-Content-Type-Options
211
- # * https://msdn.microsoft.com/en-us/library/gg622941%28v=vs.85%29.aspx
212
- # * https://blogs.msdn.microsoft.com/ie/2008/09/02/ie8-security-part-vi-beta-2-update
213
- #
214
- security.x_content_type_options 'nosniff'
215
-
216
- # X-XSS-Protection is a HTTP header to determine the behavior of the
217
- # browser in case an XSS attack is detected.
218
- #
219
- # Read more at:
220
- #
221
- # * https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
222
- # * https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#X-XSS-Protection
223
- #
224
- security.x_xss_protection '1; mode=block'
225
-
226
- # Content-Security-Policy (CSP) is a HTTP header supported by modern
227
- # browsers. It determines trusted sources of execution for dynamic
228
- # contents (JavaScript) or other web related assets: stylesheets, images,
229
- # fonts, plugins, etc.
230
- #
231
- # Web applications can send this header to mitigate Cross Site Scripting
232
- # (XSS) attacks.
233
- #
234
- # The default value allows images, scripts, AJAX, fonts and CSS from the
235
- # same origin, and does not allow any other resources to load (eg object,
236
- # frame, media, etc).
237
- #
238
- # Inline JavaScript is NOT allowed. To enable it, please use:
239
- # "script-src 'unsafe-inline'".
240
- #
241
- # Content Security Policy introduction:
242
- #
243
- # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/
244
- # * https://www.owasp.org/index.php/Content_Security_Policy
245
- # * https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29
246
- #
247
- # Inline and eval JavaScript risks:
248
- #
249
- # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/#inline-code-considered-harmful
250
- # * http://www.html5rocks.com/en/tutorials/security/content-security-policy/#eval-too
251
- #
252
- # Content Security Policy usage:
253
- #
254
- # * http://content-security-policy.com/
255
- # * https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Using_Content_Security_Policy
256
- #
257
- # Content Security Policy references:
258
- #
259
- # * https://developer.mozilla.org/en-US/docs/Web/Security/CSP/CSP_policy_directives
260
- #
261
- security.content_security_policy %{
262
- form-action 'self';
263
- frame-ancestors 'self';
264
- base-uri 'self';
265
- default-src 'none';
266
- script-src 'self';
267
- connect-src 'self';
268
- img-src 'self' https: data:;
269
- style-src 'self' 'unsafe-inline' https:;
270
- font-src 'self';
271
- object-src 'none';
272
- plugin-types application/pdf;
273
- child-src 'self';
274
- frame-src 'self';
275
- media-src 'self'
276
- }
277
-
278
- ##
279
- # FRAMEWORKS
280
- #
281
-
282
- # Configure the code that will yield each time #{app_name}::Action is included
283
- # This is useful for sharing common functionality
284
- #
285
- # See: http://www.rubydoc.info/gems/hanami-controller#Configuration
286
- controller.prepare do
287
- # include MyAuthentication # included in all the actions
288
- # before :authenticate! # run an authentication before callback
289
- end
290
-
291
- # Configure the code that will yield each time #{app_name}::View is included
292
- # This is useful for sharing common functionality
293
- #
294
- # See: http://www.rubydoc.info/gems/hanami-view#Configuration
295
- view.prepare do
296
- include Hanami::Helpers
297
- include #{app_name}::Assets::Helpers
298
- end
299
- end
300
-
301
- ##
302
- # DEVELOPMENT
303
- #
304
- configure :development do
305
- # Don't handle exceptions, render the stack trace
306
- handle_exceptions false
307
- end
308
-
309
- ##
310
- # TEST
311
- #
312
- configure :test do
313
- # Don't handle exceptions, render the stack trace
314
- handle_exceptions false
315
- end
316
-
317
- ##
318
- # PRODUCTION
319
- #
320
- configure :production do
321
- # scheme 'https'
322
- # host 'example.org'
323
- # port 443
324
-
325
- assets do
326
- # Don't compile static assets in production mode (eg. Sass, ES6)
327
- #
328
- # See: http://www.rubydoc.info/gems/hanami-assets#Configuration
329
- compile false
330
-
331
- # Use fingerprint file name for asset paths
332
- #
333
- # See: https://guides.hanamirb.org/assets/overview
334
- fingerprint true
335
-
336
- # Content Delivery Network (CDN)
337
- #
338
- # See: https://guides.hanamirb.org/assets/content-delivery-network
339
- #
340
- # scheme 'https'
341
- # host 'cdn.example.org'
342
- # port 443
343
-
344
- # Subresource Integrity
345
- #
346
- # See: https://guides.hanamirb.org/assets/content-delivery-network/#subresource-integrity
347
- subresource_integrity :sha256
348
- end
349
- end
350
- end
351
- end
352
- END
353
-
354
- #
355
- # apps/<app>/config/routes.rb
356
- #
357
- expect("apps/#{app}/config/routes.rb").to have_file_content <<-END
358
- # Configure your routes here
359
- # See: https://guides.hanamirb.org/routing/overview
360
- #
361
- # Example:
362
- # get '/hello', to: ->(env) { [200, {}, ['Hello from Hanami!']] }
363
- END
364
-
365
- #
366
- # apps/<app>/views/application_layout.rb
367
- #
368
- expect("apps/#{app}/views/application_layout.rb").to have_file_content <<~END
369
- module #{app_name}
370
- module Views
371
- class ApplicationLayout
372
- include #{app_name}::Layout
373
- end
374
- end
375
- end
376
- END
377
-
378
- #
379
- # apps/<app>/assets/favicon.ico
380
- #
381
- expect("apps/#{app}/assets/favicon.ico").to be_an_existing_file
382
-
383
- #
384
- # spec/<app>/views/application_layout_spec.rb
385
- #
386
- expect("spec/#{app}/views/application_layout_spec.rb").to be_an_existing_file
387
-
388
- #
389
- # apps/<app>/controllers/.gitkeep
390
- #
391
- expect("apps/#{app}/controllers/.gitkeep").to be_an_existing_file
392
-
393
- #
394
- # apps/<app>/assets/images/.gitkeep
395
- #
396
- expect("apps/#{app}/assets/images/.gitkeep").to be_an_existing_file
397
-
398
- #
399
- # apps/<app>/assets/javascripts/.gitkeep
400
- #
401
- expect("apps/#{app}/assets/javascripts/.gitkeep").to be_an_existing_file
402
-
403
- #
404
- # apps/<app>/assets/stylesheets/.gitkeep
405
- #
406
- expect("apps/#{app}/assets/stylesheets/.gitkeep").to be_an_existing_file
407
-
408
- #
409
- # spec/<app>/features/.gitkeep
410
- #
411
- expect("spec/#{app}/features/.gitkeep").to be_an_existing_file
412
-
413
- #
414
- # spec/<app>/controllers/.gitkeep
415
- #
416
- expect("spec/#{app}/controllers/.gitkeep").to be_an_existing_file
417
-
418
- #
419
- # config/environment.rb
420
- #
421
- expect("config/environment.rb").to have_file_content <<-END
422
- require 'bundler/setup'
423
- require 'hanami/setup'
424
- require 'hanami/model'
425
- require_relative '../lib/#{project}'
426
- require_relative '../apps/web/application'
427
- require_relative '../apps/#{app}/application'
428
-
429
- Hanami.configure do
430
- mount #{app_name}::Application, at: '/#{app}'
431
- mount Web::Application, at: '/'
432
-
433
- model do
434
- ##
435
- # Database adapter
436
- #
437
- # Available options:
438
- #
439
- # * SQL adapter
440
- # adapter :sql, 'sqlite://db/#{project}_development.sqlite3'
441
- # adapter :sql, 'postgresql://localhost/#{project}_development'
442
- # adapter :sql, 'mysql://localhost/#{project}_development'
443
- #
444
- adapter :sql, ENV.fetch('DATABASE_URL')
445
-
446
- ##
447
- # Migrations
448
- #
449
- migrations 'db/migrations'
450
- schema 'db/schema.sql'
451
- end
452
-
453
- mailer do
454
- root 'lib/#{project}/mailers'
455
-
456
- # See https://guides.hanamirb.org/mailers/delivery
457
- delivery :test
458
- end
459
-
460
- environment :development do
461
- # See: https://guides.hanamirb.org/projects/logging
462
- logger level: :debug
463
- end
464
-
465
- environment :production do
466
- logger level: :info, formatter: :json, filter: []
467
-
468
- mailer do
469
- delivery :smtp, address: ENV.fetch('SMTP_HOST'), port: ENV.fetch('SMTP_PORT')
470
- end
471
- end
472
- end
473
- END
474
-
475
- #
476
- # .env.development
477
- #
478
- expect(".env.development").to have_file_content(%r{# Define ENV variables for development environment})
479
- expect(".env.development").to have_file_content(%r{DATABASE_URL="sqlite://db/#{project}_development.sqlite"})
480
- expect(".env.development").to have_file_content(%r{SERVE_STATIC_ASSETS="true"})
481
- expect(".env.development").to have_file_content(%r{WEB_SESSIONS_SECRET="[\w]{64}"})
482
- expect(".env.development").to have_file_content(%r{#{app_upcase}_SESSIONS_SECRET="[\w]{64}"})
483
-
484
- #
485
- # .env.test
486
- #
487
- expect(".env.test").to have_file_content(%r{# Define ENV variables for test environment})
488
- expect(".env.test").to have_file_content(%r{DATABASE_URL="sqlite://db/#{project}_test.sqlite"})
489
- expect(".env.test").to have_file_content(%r{SERVE_STATIC_ASSETS="true"})
490
- expect(".env.test").to have_file_content(%r{WEB_SESSIONS_SECRET="[\w]{64}"})
491
- expect(".env.test").to have_file_content(%r{#{app_upcase}_SESSIONS_SECRET="[\w]{64}"})
492
- end
493
- end
494
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/utils/string"
4
-
5
- RSpec.shared_examples "a new migration" do
6
- let(:migration) { Hanami::Utils::String.new(input).underscore.to_s }
7
-
8
- it "generates migration" do
9
- project = "bookshelf_generate_migration_#{Random.rand(100_000_000)}"
10
-
11
- with_project(project) do
12
- run_cmd "hanami generate migration #{input}", migration
13
-
14
- #
15
- # db/migrations/<timestamp>_<migration>.rb
16
- #
17
- migrations = Pathname.new("db").join("migrations").children
18
- file = migrations.find do |child|
19
- child.to_s.include?(migration)
20
- end
21
-
22
- expect(file).to_not be_nil, "Expected to find a migration matching: #{file}.\nFound: #{migrations.map(&:basename).join(' ')}"
23
-
24
- expect(file.to_s).to have_file_content <<~END
25
- Hanami::Model.migration do
26
- change do
27
- end
28
- end
29
- END
30
- end
31
- end
32
- end
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/utils/string"
4
-
5
- RSpec.shared_examples "a new model" do
6
- let(:model) { Hanami::Utils::String.new(input).underscore.to_s }
7
-
8
- it "generates model" do
9
- class_name = Hanami::Utils::String.new(model).classify
10
- table_name = Hanami::Utils::String.new(model).pluralize
11
- project = "bookshelf_generate_model_#{Random.rand(100_000_000)}"
12
-
13
- with_project(project) do
14
- output = [
15
- "create lib/#{project}/entities/#{model}.rb",
16
- "create lib/#{project}/repositories/#{model}_repository.rb",
17
- /create db\/migrations\/(\d+)_create_#{table_name}.rb/,
18
- "create spec/#{project}/entities/#{model}_spec.rb",
19
- "create spec/#{project}/repositories/#{model}_repository_spec.rb"
20
- ]
21
-
22
- run_cmd "hanami generate model #{input}", output
23
-
24
- #
25
- # lib/<project>/entities/<model>.rb
26
- #
27
- expect("lib/#{project}/entities/#{model}.rb").to have_file_content <<~END
28
- class #{class_name} < Hanami::Entity
29
- end
30
- END
31
-
32
- #
33
- # lib/<project>/repositories/<model>_repository.rb
34
- #
35
- expect("lib/#{project}/repositories/#{model}_repository.rb").to have_file_content <<~END
36
- class #{class_name}Repository < Hanami::Repository
37
- end
38
- END
39
-
40
- #
41
- # db/migrations/<timestamp>_create_<models>.rb
42
- #
43
- migrations = Pathname.new("db").join("migrations").children
44
- file = migrations.find do |child|
45
- child.to_s.include?("create_#{table_name}")
46
- end
47
- expect(file).to_not be_nil, "Expected to find a migration matching: create_#{table_name}.\nFound: #{migrations.map(&:basename).join(' ')}"
48
-
49
- expect(file.to_s).to have_file_content <<~END
50
- Hanami::Model.migration do
51
- change do
52
- create_table :#{table_name} do
53
- primary_key :id
54
-
55
- column :created_at, DateTime, null: false
56
- column :updated_at, DateTime, null: false
57
- end
58
- end
59
- end
60
- END
61
-
62
- #
63
- # spec/<project>/entities/<model>_spec.rb
64
- #
65
- expect("spec/#{project}/entities/#{model}_spec.rb").to have_file_content <<~END
66
- RSpec.describe #{class_name}, type: :entity do
67
- # place your tests here
68
- end
69
- END
70
-
71
- #
72
- # spec/<project>/repositories/<model>_repository_spec.rb
73
- #
74
- expect("spec/#{project}/repositories/#{model}_repository_spec.rb").to have_file_content <<~END
75
- RSpec.describe #{class_name}Repository, type: :repository do
76
- # place your tests here
77
- end
78
- END
79
- end
80
- end
81
- end
@@ -1,97 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/utils/string"
4
-
5
- RSpec.shared_examples "a new project" do
6
- let(:project) { Hanami::Utils::String.new(input).underscore.to_s }
7
-
8
- it 'generates vanilla project' do
9
- run_cmd "hanami new #{input}"
10
-
11
- [
12
- "create lib/#{project}.rb",
13
- "create lib/#{project}/entities/.gitkeep",
14
- "create lib/#{project}/repositories/.gitkeep",
15
- "create lib/#{project}/mailers/.gitkeep",
16
- "create lib/#{project}/mailers/templates/.gitkeep",
17
- "create spec/#{project}/entities/.gitkeep",
18
- "create spec/#{project}/repositories/.gitkeep",
19
- "create spec/#{project}/mailers/.gitkeep"
20
- ].each do |output|
21
- expect(all_output).to match(/#{output}/)
22
- end
23
-
24
- within_project_directory(project) do
25
- #
26
- # .hanamirc
27
- #
28
- expect(".hanamirc").to have_file_content %r{project=#{project}}
29
-
30
- #
31
- # .env.development
32
- #
33
- expect(".env.development").to have_file_content(%r{DATABASE_URL="sqlite://db/#{project}_development.sqlite"})
34
-
35
- #
36
- # .env.test
37
- #
38
- expect(".env.test").to have_file_content(%r{DATABASE_URL="sqlite://db/#{project}_test.sqlite"})
39
-
40
- #
41
- # config/environment.rb
42
- #
43
- expect("config/environment.rb").to have_file_content %r{require_relative '../lib/#{project}'}
44
-
45
- project_module = Hanami::Utils::String.new(project).classify
46
-
47
- #
48
- # lib/<project>.rb
49
- #
50
- expect("lib/#{project}.rb").to have_file_content <<~END
51
- module #{project_module}
52
- end
53
- END
54
-
55
- #
56
- # lib/<project>/entities/.gitkeep
57
- #
58
- expect("lib/#{project}/entities/.gitkeep").to be_an_existing_file
59
-
60
- #
61
- # lib/<project>/mailers/.gitkeep
62
- #
63
- expect("lib/#{project}/mailers/.gitkeep").to be_an_existing_file
64
-
65
- #
66
- # lib/<project>/mailers/templates/.gitkeep
67
- #
68
- expect("lib/#{project}/mailers/templates/.gitkeep").to be_an_existing_file
69
-
70
- #
71
- # spec/<project>/entities/.gitkeep
72
- #
73
- expect("spec/#{project}/entities/.gitkeep").to be_an_existing_file
74
-
75
- #
76
- # spec/<project>/repositories/.gitkeep
77
- #
78
- expect("spec/#{project}/repositories/.gitkeep").to be_an_existing_file
79
-
80
- #
81
- # spec/<project>/mailers/.gitkeep
82
- #
83
- expect("spec/#{project}/mailers/.gitkeep").to be_an_existing_file
84
-
85
- #
86
- # .gitignore
87
- #
88
- expect(".gitignore").to have_file_content <<-END
89
- /db/*.sqlite
90
- /public/assets*
91
- /tmp
92
- .env.local
93
- .env.*.local
94
- END
95
- end
96
- end
97
- end