hanami 2.1.0.rc1 → 2.1.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/hanami.gemspec +2 -2
  4. data/lib/hanami/app.rb +0 -5
  5. data/lib/hanami/config/actions.rb +3 -4
  6. data/lib/hanami/config/assets.rb +1 -1
  7. data/lib/hanami/config/views.rb +10 -2
  8. data/lib/hanami/config.rb +21 -16
  9. data/lib/hanami/extensions/view/context.rb +122 -10
  10. data/lib/hanami/extensions/view/part.rb +14 -2
  11. data/lib/hanami/extensions/view/scope.rb +7 -0
  12. data/lib/hanami/extensions/view/slice_configured_context.rb +12 -8
  13. data/lib/hanami/extensions/view/slice_configured_helpers.rb +12 -1
  14. data/lib/hanami/extensions/view/slice_configured_part.rb +4 -5
  15. data/lib/hanami/extensions/view/slice_configured_view.rb +12 -4
  16. data/lib/hanami/extensions/view/standard_helpers.rb +4 -0
  17. data/lib/hanami/extensions/view.rb +5 -3
  18. data/lib/hanami/helpers/assets_helper.rb +71 -70
  19. data/lib/hanami/helpers/form_helper/form_builder.rb +54 -54
  20. data/lib/hanami/helpers/form_helper/values.rb +8 -8
  21. data/lib/hanami/helpers/form_helper.rb +9 -9
  22. data/lib/hanami/providers/assets.rb +4 -1
  23. data/lib/hanami/rake_tasks.rb +1 -9
  24. data/lib/hanami/slice.rb +10 -0
  25. data/lib/hanami/version.rb +1 -1
  26. data/spec/integration/assets/assets_spec.rb +67 -24
  27. data/spec/integration/assets/cross_slice_assets_helpers_spec.rb +130 -0
  28. data/spec/integration/view/context/assets_spec.rb +57 -31
  29. data/spec/support/app_integration.rb +12 -6
  30. data/spec/unit/hanami/config/render_detailed_errors_spec.rb +1 -1
  31. data/spec/unit/hanami/helpers/assets_helper/asset_url_spec.rb +11 -0
  32. data/spec/unit/hanami/version_spec.rb +1 -1
  33. metadata +13 -11
@@ -18,39 +18,17 @@ RSpec.describe "Assets", :app_integration do
18
18
  end
19
19
  RUBY
20
20
 
21
- write "config/assets.mjs", <<~JS
21
+ write "config/assets.js", <<~JS
22
22
  import * as assets from "hanami-assets";
23
23
  await assets.run();
24
24
  JS
25
25
 
26
26
  write "package.json", <<~JSON
27
27
  {
28
- "scripts": {
29
- "assets": "node config/assets.mjs"
30
- }
28
+ "type": "module"
31
29
  }
32
30
  JSON
33
31
 
34
- write "config/routes.rb", <<~RUBY
35
- module TestApp
36
- class Routes < Hanami::Routes
37
- get "posts/:id/edit", to: "posts.edit"
38
- put "posts/:id", to: "posts.update"
39
- end
40
- end
41
- RUBY
42
-
43
- write "app/action.rb", <<~RUBY
44
- # auto_register: false
45
-
46
- require "hanami/action"
47
-
48
- module TestApp
49
- class Action < Hanami::Action
50
- end
51
- end
52
- RUBY
53
-
54
32
  write "app/view.rb", <<~RUBY
55
33
  # auto_register: false
56
34
 
@@ -109,4 +87,69 @@ RSpec.describe "Assets", :app_integration do
109
87
  expect(assets["app.css"].to_s).to match(%r{/assets/app-[A-Z0-9]{8}.css})
110
88
  expect(assets["app.js"].to_s).to match(%r{/assets/app-[A-Z0-9]{8}.js})
111
89
  end
90
+
91
+ describe "slice with assets" do
92
+ def before_prepare
93
+ write "slices/main/view.rb", <<~RUBY
94
+ # auto_register: false
95
+
96
+ module Main
97
+ class View < TestApp::View
98
+ end
99
+ end
100
+ RUBY
101
+
102
+ write "slices/main/views/posts/show.rb", <<~RUBY
103
+ module Main
104
+ module Views
105
+ module Posts
106
+ class Show < Main::View
107
+ end
108
+ end
109
+ end
110
+ end
111
+ RUBY
112
+
113
+ write "slices/main/templates/posts/show.html.erb", <<~ERB
114
+ <%= stylesheet_tag("app") %>
115
+ <%= javascript_tag("app") %>
116
+ ERB
117
+
118
+ write "slices/main/assets/js/app.ts", <<~TS
119
+ import "../css/app.css";
120
+
121
+ console.log("Hello from main slice index.ts");
122
+ TS
123
+
124
+ write "slices/main/assets/css/app.css", <<~CSS
125
+ .btn {
126
+ background: #f00;
127
+ }
128
+ CSS
129
+ end
130
+
131
+ specify "the slice's assets are available in its own and distinct `assets` component" do
132
+ compile_assets!
133
+
134
+ output = Main::Slice["views.posts.show"].call.to_s
135
+
136
+ expect(output).to match(%r{<link href="/assets/main/app-[A-Z0-9]{8}.css" type="text/css" rel="stylesheet">})
137
+ expect(output).to match(%r{<script src="/assets/main/app-[A-Z0-9]{8}.js" type="text/javascript"></script>})
138
+
139
+ assets = Main::Slice["assets"]
140
+
141
+ expect(assets["app.css"].to_s).to match(%r{/assets/main/app-[A-Z0-9]{8}.css})
142
+ expect(assets["app.js"].to_s).to match(%r{/assets/main/app-[A-Z0-9]{8}.js})
143
+ end
144
+ end
145
+
146
+ describe "slice without assets" do
147
+ def before_prepare
148
+ write "slices/main/.keep", ""
149
+ end
150
+
151
+ it "does not have an assets component" do
152
+ expect(Main::Slice.key?("assets")).to be false
153
+ end
154
+ end
112
155
  end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/test"
4
+ require "stringio"
5
+
6
+ RSpec.describe "Cross-slice assets via helpers", :app_integration do
7
+ include Rack::Test::Methods
8
+ let(:app) { Hanami.app }
9
+ let(:root) { make_tmp_directory }
10
+
11
+ before do
12
+ with_directory(root) do
13
+ write "config/app.rb", <<~RUBY
14
+ module TestApp
15
+ class App < Hanami::App
16
+ config.logger.stream = StringIO.new
17
+ end
18
+ end
19
+ RUBY
20
+
21
+ write "config/slices/admin.rb", <<~RUBY
22
+ module Admin
23
+ class Slice < Hanami::Slice
24
+ # TODO: we should update `import` to make importing from the app nicer
25
+ # TODO: this test failed when I tried doing `as: "app"` (string instead of symbol); fix this in dry-system
26
+ import keys: ["assets"], from: Hanami.app.container, as: :app
27
+ end
28
+ end
29
+ RUBY
30
+
31
+ write "config/assets.js", <<~JS
32
+ import * as assets from "hanami-assets";
33
+ await assets.run();
34
+ JS
35
+
36
+ write "package.json", <<~JSON
37
+ {
38
+ "type": "module"
39
+ }
40
+ JSON
41
+
42
+ write "app/view.rb", <<~RUBY
43
+ # auto_register: false
44
+
45
+ require "hanami/view"
46
+
47
+ module TestApp
48
+ class View < Hanami::View
49
+ config.layout = nil
50
+ end
51
+ end
52
+ RUBY
53
+
54
+ write "app/assets/js/app.ts", <<~TS
55
+ import "../css/app.css";
56
+
57
+ console.log("Hello from index.ts");
58
+ TS
59
+
60
+ write "app/assets/css/app.css", <<~CSS
61
+ .btn {
62
+ background: #f00;
63
+ }
64
+ CSS
65
+
66
+ write "slices/admin/assets/js/app.ts", <<~TS
67
+ import "../css/app.css";
68
+
69
+ console.log("Hello from admin's index.ts");
70
+ TS
71
+
72
+ write "slices/admin/assets/css/app.css", <<~CSS
73
+ .btn {
74
+ background: #f00;
75
+ }
76
+ CSS
77
+
78
+ write "slices/admin/view.rb", <<~RUBY
79
+ # auto_register: false
80
+
81
+ module Admin
82
+ class View < TestApp::View
83
+ end
84
+ end
85
+ RUBY
86
+
87
+ write "slices/admin/views/posts/show.rb", <<~RUBY
88
+ module Admin
89
+ module Views
90
+ module Posts
91
+ class Show < Admin::View
92
+ end
93
+ end
94
+ end
95
+ end
96
+ RUBY
97
+
98
+ write "slices/admin/views/context.rb", <<~RUBY
99
+ # auto_register: false
100
+
101
+ require "hanami/view"
102
+
103
+ module Admin
104
+ module Views
105
+ class Context < Hanami::View::Context
106
+ include Deps[app_assets: "app.assets"]
107
+ end
108
+ end
109
+ end
110
+ RUBY
111
+
112
+ write "slices/admin/templates/posts/show.html.erb", <<~ERB
113
+ <%= stylesheet_tag(app_assets["app.css"]) %>
114
+ <%= javascript_tag(app_assets["app.js"]) %>
115
+ ERB
116
+
117
+ before_prepare if respond_to?(:before_prepare)
118
+ require "hanami/prepare"
119
+ end
120
+ end
121
+
122
+ specify "assets are available in helpers and in `assets` component" do
123
+ compile_assets!
124
+
125
+ output = Admin::Slice["views.posts.show"].call.to_s
126
+
127
+ expect(output).to match(%r{<link href="/assets/app-[A-Z0-9]{8}.css" type="text/css" rel="stylesheet">})
128
+ expect(output).to match(%r{<script src="/assets/app-[A-Z0-9]{8}.js" type="text/javascript"></script>})
129
+ end
130
+ end
@@ -3,51 +3,77 @@
3
3
  require "hanami"
4
4
 
5
5
  RSpec.describe "App view / Context / Assets", :app_integration do
6
+ subject(:context) { context_class.new }
7
+ let(:context_class) { TestApp::Views::Context }
8
+
6
9
  before do
7
- module TestApp
8
- class App < Hanami::App
9
- end
10
- end
10
+ with_directory(make_tmp_directory) do
11
+ write "config/app.rb", <<~RUBY
12
+ module TestApp
13
+ class App < Hanami::App
14
+ config.logger.stream = File::NULL
15
+ end
16
+ end
17
+ RUBY
11
18
 
12
- Hanami.prepare
19
+ write "app/views/context.rb", <<~RUBY
20
+ # auto_register: false
13
21
 
14
- module TestApp
15
- module Views
16
- class Context < Hanami::View::Context
22
+ require "hanami/view/context"
23
+
24
+ module TestApp
25
+ module Views
26
+ class Context < Hanami::View::Context
27
+ end
28
+ end
17
29
  end
18
- end
30
+ RUBY
31
+
32
+ before_prepare if respond_to?(:before_prepare)
33
+ require "hanami/prepare"
19
34
  end
20
35
  end
21
36
 
22
- let(:context_class) { TestApp::Views::Context }
23
- subject(:context) { context_class.new }
37
+ context "assets present and hanami-assets bundled" do
38
+ def before_prepare
39
+ write "app/assets/.keep", ""
40
+ end
24
41
 
25
- describe "#assets" do
26
- context "without assets provider" do
27
- xit "raises error" do
28
- allow(Hanami).to receive(:bundled?).with("hanami-assets").and_return(false)
42
+ it "is the app assets by default" do
43
+ expect(context.assets).to be TestApp::App[:assets]
44
+ end
45
+ end
29
46
 
30
- expect { context.assets }
31
- .to raise_error(Hanami::ComponentLoadError, /hanami-assets/)
32
- end
47
+ context "assets not present" do
48
+ it "raises error" do
49
+ expect { context.assets }.to raise_error(Hanami::ComponentLoadError, /assets directory\?/)
33
50
  end
51
+ end
34
52
 
35
- context "with assets provider" do
36
- it "is the app assets by default" do
37
- expect(context.assets).to be TestApp::App[:assets]
38
- end
53
+ context "hanami-assets not bundled" do
54
+ def before_prepare
55
+ # These must be here instead of an ordinary before hook because the Hanami.bundled? check for
56
+ # assets is done as part of requiring "hanami/prepare" above.
57
+ allow(Hanami).to receive(:bundled?).and_call_original
58
+ allow(Hanami).to receive(:bundled?).with("hanami-assets").and_return(false)
39
59
 
40
- context "injected assets" do
41
- subject(:context) {
42
- context_class.new(assets: assets)
43
- }
60
+ write "app/assets/.keep", ""
61
+ end
44
62
 
45
- let(:assets) { double(:assets) }
63
+ it "raises error" do
64
+ expect { context.assets }.to raise_error(Hanami::ComponentLoadError, /hanami-assets gem/)
65
+ end
66
+ end
46
67
 
47
- it "is the injected assets" do
48
- expect(context.assets).to be assets
49
- end
50
- end
68
+ context "injected assets" do
69
+ subject(:context) {
70
+ context_class.new(assets: assets)
71
+ }
72
+
73
+ let(:assets) { double(:assets) }
74
+
75
+ it "is the injected assets" do
76
+ expect(context.assets).to be assets
51
77
  end
52
78
  end
53
79
  end
@@ -29,12 +29,16 @@ module RSpec
29
29
 
30
30
  private
31
31
 
32
+ # TODO: make slice-aware
32
33
  def stub_assets(*assets)
33
34
  manifest_hash = assets.each_with_object({}) { |source_path, hsh|
34
35
  hsh[source_path] = {url: File.join("/assets", source_path)}
35
36
  }
36
37
 
37
- write "public/assets.json", JSON.generate(manifest_hash)
38
+ write "public/assets/assets.json", JSON.generate(manifest_hash)
39
+
40
+ # An assets dir isrequired to load the assets provider
41
+ write "app/assets/.keep", ""
38
42
  end
39
43
 
40
44
  def compile_assets!
@@ -44,7 +48,11 @@ module RSpec
44
48
  require "hanami/cli/command"
45
49
  require "hanami/cli/commands/app/command"
46
50
  require "hanami/cli/commands/app/assets/compile"
47
- assets_compile = Hanami::CLI::Commands::App::Assets::Compile.new(config: Hanami.app.config.assets)
51
+ assets_compile = Hanami::CLI::Commands::App::Assets::Compile.new(
52
+ config: Hanami.app.config.assets,
53
+ out: File.new(File::NULL, "w"),
54
+ err: File.new(File::NULL, "w"),
55
+ )
48
56
 
49
57
  with_directory(Hanami.app.root) { assets_compile.call }
50
58
  end
@@ -62,16 +70,14 @@ module RSpec
62
70
  root = Hanami.app.root
63
71
 
64
72
  with_directory(root) do
65
- write("config/assets.mjs", <<~JS) unless root.join("config", "assets.mjs").exist?
73
+ write("config/assets.js", <<~JS) unless root.join("config", "assets.js").exist?
66
74
  import * as assets from "hanami-assets";
67
75
  await assets.run();
68
76
  JS
69
77
 
70
78
  write("package.json", <<~JSON) unless root.join("package.json").exist?
71
79
  {
72
- "scripts": {
73
- "assets": "node config/assets.mjs"
74
- }
80
+ "type": "module"
75
81
  }
76
82
  JSON
77
83
  end
@@ -15,7 +15,7 @@ RSpec.describe Hanami::Config, "#render_detailed_errors" do
15
15
 
16
16
  context "test mode" do
17
17
  let(:env) { :test }
18
- it { is_expected.to be true }
18
+ it { is_expected.to be false }
19
19
  end
20
20
 
21
21
  context "production mode" do
@@ -106,4 +106,15 @@ RSpec.describe Hanami::Helpers::AssetsHelper, "#asset_url", :app_integration do
106
106
  end
107
107
  end
108
108
  end
109
+
110
+ context "given an asset object" do
111
+ it "returns the URL for the asset" do
112
+ asset = Hanami::Assets::Asset.new(
113
+ path: "/foo/bar.js",
114
+ base_url: Hanami.app.config.assets.base_url
115
+ )
116
+
117
+ expect(asset_url(asset)).to eq "/foo/bar.js"
118
+ end
119
+ end
109
120
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  RSpec.describe "Hanami::VERSION" do
4
4
  it "returns current version" do
5
- expect(Hanami::VERSION).to eq("2.1.0.rc1")
5
+ expect(Hanami::VERSION).to eq("2.1.0.rc3")
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0.rc1
4
+ version: 2.1.0.rc3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-01 00:00:00.000000000 Z
11
+ date: 2024-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -160,30 +160,30 @@ dependencies:
160
160
  name: hanami-cli
161
161
  requirement: !ruby/object:Gem::Requirement
162
162
  requirements:
163
- - - "~>"
163
+ - - '='
164
164
  - !ruby/object:Gem::Version
165
- version: 2.1.beta
165
+ version: 2.1.0.rc3
166
166
  type: :runtime
167
167
  prerelease: false
168
168
  version_requirements: !ruby/object:Gem::Requirement
169
169
  requirements:
170
- - - "~>"
170
+ - - '='
171
171
  - !ruby/object:Gem::Version
172
- version: 2.1.beta
172
+ version: 2.1.0.rc3
173
173
  - !ruby/object:Gem::Dependency
174
174
  name: hanami-utils
175
175
  requirement: !ruby/object:Gem::Requirement
176
176
  requirements:
177
177
  - - "~>"
178
178
  - !ruby/object:Gem::Version
179
- version: 2.1.beta
179
+ version: 2.1.rc
180
180
  type: :runtime
181
181
  prerelease: false
182
182
  version_requirements: !ruby/object:Gem::Requirement
183
183
  requirements:
184
184
  - - "~>"
185
185
  - !ruby/object:Gem::Version
186
- version: 2.1.beta
186
+ version: 2.1.rc
187
187
  - !ruby/object:Gem::Dependency
188
188
  name: zeitwerk
189
189
  requirement: !ruby/object:Gem::Requirement
@@ -325,6 +325,7 @@ files:
325
325
  - spec/integration/action/view_rendering/view_context_spec.rb
326
326
  - spec/integration/action/view_rendering_spec.rb
327
327
  - spec/integration/assets/assets_spec.rb
328
+ - spec/integration/assets/cross_slice_assets_helpers_spec.rb
328
329
  - spec/integration/assets/serve_static_assets_spec.rb
329
330
  - spec/integration/code_loading/loading_from_app_spec.rb
330
331
  - spec/integration/code_loading/loading_from_lib_spec.rb
@@ -446,11 +447,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
446
447
  version: '3.0'
447
448
  required_rubygems_version: !ruby/object:Gem::Requirement
448
449
  requirements:
449
- - - ">"
450
+ - - ">="
450
451
  - !ruby/object:Gem::Version
451
- version: 1.3.1
452
+ version: '0'
452
453
  requirements: []
453
- rubygems_version: 3.4.13
454
+ rubygems_version: 3.5.6
454
455
  signing_key:
455
456
  specification_version: 4
456
457
  summary: The web, with simplicity
@@ -466,6 +467,7 @@ test_files:
466
467
  - spec/integration/action/view_rendering/view_context_spec.rb
467
468
  - spec/integration/action/view_rendering_spec.rb
468
469
  - spec/integration/assets/assets_spec.rb
470
+ - spec/integration/assets/cross_slice_assets_helpers_spec.rb
469
471
  - spec/integration/assets/serve_static_assets_spec.rb
470
472
  - spec/integration/code_loading/loading_from_app_spec.rb
471
473
  - spec/integration/code_loading/loading_from_lib_spec.rb