vite_rails 1.0.8 → 1.0.9

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 +5 -1
  3. data/CONTRIBUTING.md +0 -1
  4. data/lib/install/template.rb +1 -1
  5. data/lib/tasks/vite/build.rake +1 -5
  6. data/lib/tasks/vite/clean.rake +1 -3
  7. data/lib/tasks/vite/verify_install.rake +3 -3
  8. data/lib/vite_rails.rb +14 -25
  9. data/lib/vite_rails/builder.rb +11 -4
  10. data/lib/vite_rails/commands.rb +50 -10
  11. data/lib/vite_rails/config.rb +35 -23
  12. data/lib/vite_rails/dev_server_proxy.rb +27 -18
  13. data/lib/vite_rails/helper.rb +4 -2
  14. data/lib/vite_rails/manifest.rb +4 -3
  15. data/lib/vite_rails/runner.rb +2 -5
  16. data/lib/vite_rails/version.rb +1 -1
  17. data/package.json +1 -1
  18. data/test/builder_test.rb +27 -22
  19. data/test/commands_test.rb +67 -0
  20. data/test/configuration_test.rb +88 -46
  21. data/test/dev_server_proxy_test.rb +101 -0
  22. data/test/dev_server_test.rb +0 -30
  23. data/test/engine_rake_tasks_test.rb +55 -17
  24. data/test/helper_test.rb +37 -105
  25. data/test/manifest_test.rb +33 -29
  26. data/test/mode_test.rb +6 -11
  27. data/test/mounted_app/test/dummy/config/vite.json +5 -11
  28. data/test/mounted_app/test/dummy/package.json +2 -1
  29. data/test/mounted_app/test/dummy/yarn.lock +208 -0
  30. data/test/rake_tasks_test.rb +5 -19
  31. data/test/runner_test.rb +31 -0
  32. data/test/test_app/app/{javascript → frontend}/entrypoints/application.js +0 -0
  33. data/test/test_app/config/vite.json +0 -2
  34. data/test/test_app/config/vite_additional_paths.json +5 -0
  35. data/test/test_app/config/vite_public_dir.json +5 -0
  36. data/test/test_app/public/vite-production/manifest.json +22 -0
  37. data/test/test_helper.rb +48 -14
  38. metadata +21 -23
  39. data/test/command_test.rb +0 -35
  40. data/test/dev_server_runner_test.rb +0 -83
  41. data/test/test_app/app/javascript/entrypoints/multi_entry.css +0 -4
  42. data/test/test_app/app/javascript/entrypoints/multi_entry.js +0 -4
  43. data/test/test_app/config/vite_public_root.yml +0 -20
  44. data/test/test_app/public/vite/manifest.json +0 -36
  45. data/test/vite_runner_test.rb +0 -59
  46. data/test/webpacker_test.rb +0 -15
@@ -31,7 +31,7 @@ class ViteRails::Manifest
31
31
  # Example:
32
32
  # ViteRails.manifest.lookup('calendar.js')
33
33
  # # { "file" => "/vite/assets/calendar-1016838bab065ae1e122.js", "imports" => [] }
34
- def lookup(name, type:)
34
+ def lookup(name, type: nil)
35
35
  build if should_build?
36
36
 
37
37
  find_manifest_entry(with_file_extension(name, type))
@@ -92,7 +92,8 @@ private
92
92
  def with_file_extension(name, entry_type)
93
93
  return name unless File.extname(name.to_s).empty?
94
94
 
95
- "#{ name }.#{ extension_for_type(entry_type) }"
95
+ extension = extension_for_type(entry_type)
96
+ extension ? "#{ name }.#{ extension }" : name
96
97
  end
97
98
 
98
99
  # Internal: Scopes the paths in the manifest to the output folder in public.
@@ -106,7 +107,7 @@ private
106
107
  when :javascript then 'js'
107
108
  when :stylesheet then 'css'
108
109
  when :typescript then dev_server_running? ? 'ts' : 'js'
109
- else entry_type.to_s
110
+ else entry_type
110
111
  end
111
112
  end
112
113
 
@@ -31,9 +31,8 @@ private
31
31
  cmd = vite_executable
32
32
  cmd.prepend('node', '--inspect-brk') if args.include?('--debug')
33
33
  cmd.prepend('node', '--trace-deprecation') if args.delete('--trace-deprecation')
34
- args.append('--mode', ENV['RAILS_ENV']) unless args.include?('--mode') || args.include?('-m')
34
+ args.append('--mode', ViteRails.mode) unless args.include?('--mode') || args.include?('-m')
35
35
  cmd += args
36
- puts cmd.join(' ')
37
36
  Dir.chdir(File.expand_path('.', Dir.pwd)) { Kernel.exec(ViteRails.env, *cmd) }
38
37
  end
39
38
 
@@ -49,8 +48,6 @@ private
49
48
 
50
49
  # Internal: Returns a path where a Vite executable should be found.
51
50
  def vite_bin_path
52
- ENV["#{ ViteRails::ENV_PREFIX }_VITE_BIN_PATH"] || `yarn bin vite`.chomp
53
- rescue StandardError
54
- "#{ `npm bin`.chomp }/vite"
51
+ ENV["#{ ViteRails::ENV_PREFIX }_VITE_BIN_PATH"] || `yarn bin vite`.chomp.presence || "#{ `npm bin`.chomp }/vite"
55
52
  end
56
53
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ViteRails
4
- VERSION = '1.0.8'
4
+ VERSION = '1.0.9'
5
5
  end
@@ -11,6 +11,6 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "vite": "^2.0.0-beta.34",
14
- "vite-plugin-ruby": "^1.0.2"
14
+ "vite-plugin-ruby": "^1.0.3"
15
15
  }
16
16
  }
@@ -2,27 +2,26 @@
2
2
 
3
3
  require 'test_helper'
4
4
 
5
- class BuilderTest < Minitest::Test
6
- def remove_files_digest_path
5
+ class BuilderTest < ViteRails::Test
6
+ def setup
7
+ refresh_config
7
8
  ViteRails.builder.send(:files_digest_path).tap do |path|
8
9
  path.delete if path.exist?
9
10
  end
10
11
  end
11
12
 
12
- def setup
13
- remove_files_digest_path
13
+ def teardown
14
+ setup
14
15
  end
15
16
 
16
- def teardown
17
- remove_files_digest_path
17
+ def vite_env
18
+ ViteRails.builder.send(:vite_env)
18
19
  end
19
20
 
20
21
  def test_custom_environment_variables
21
- assert_nil ViteRails.builder.send(:vite_env)['FOO']
22
+ assert_nil vite_env['FOO']
22
23
  ViteRails.env['FOO'] = 'BAR'
23
- assert ViteRails.builder.send(:vite_env)['FOO'] == 'BAR'
24
- ensure
25
- ViteRails.env = {}
24
+ assert vite_env['FOO'] == 'BAR'
26
25
  end
27
26
 
28
27
  def test_freshness
@@ -35,21 +34,19 @@ class BuilderTest < Minitest::Test
35
34
  end
36
35
 
37
36
  def test_freshness_on_build_success
38
- status = OpenStruct.new(success?: true)
39
-
40
37
  assert ViteRails.builder.stale?
38
+ status = OpenStruct.new(success?: true)
41
39
  Open3.stub :capture3, [:sterr, :stdout, status] do
42
- ViteRails.builder.build
40
+ assert ViteRails.builder.build
43
41
  assert ViteRails.builder.fresh?
44
42
  end
45
43
  end
46
44
 
47
45
  def test_freshness_on_build_fail
48
- status = OpenStruct.new(success?: false)
49
-
50
46
  assert ViteRails.builder.stale?
47
+ status = OpenStruct.new(success?: false)
51
48
  Open3.stub :capture3, [:sterr, :stdout, status] do
52
- ViteRails.builder.build
49
+ assert !ViteRails.builder.build
53
50
  assert ViteRails.builder.fresh?
54
51
  end
55
52
  end
@@ -58,15 +55,23 @@ class BuilderTest < Minitest::Test
58
55
  assert_equal ViteRails.builder.send(:files_digest_path).basename.to_s, "last-compilation-digest-#{ ViteRails.config.mode }"
59
56
  end
60
57
 
58
+ def test_watched_files_digest
59
+ previous_digest = ViteRails.builder.send(:watched_files_digest)
60
+ refresh_config
61
+ assert_equal previous_digest, ViteRails.builder.send(:watched_files_digest)
62
+ end
63
+
61
64
  def test_external_env_variables
62
- ViteRails.env = {}
63
- assert_equal ViteRails.builder.send(:vite_env)['VITE_RUBY_MODE'], 'production'
64
- assert_equal ViteRails.builder.send(:vite_env)['VITE_RUBY_ROOT'], Rails.root.to_s
65
+ assert_equal 'production', vite_env['VITE_RUBY_MODE']
66
+ assert_equal Rails.root.to_s, vite_env['VITE_RUBY_ROOT']
65
67
 
66
68
  ENV['VITE_RUBY_MODE'] = 'foo.bar'
67
69
  ENV['VITE_RUBY_ROOT'] = '/baz'
68
-
69
- assert_equal ViteRails.builder.send(:vite_env)['VITE_RUBY_MODE'], 'foo.bar'
70
- assert_equal ViteRails.builder.send(:vite_env)['VITE_RUBY_ROOT'], '/baz'
70
+ refresh_config
71
+ assert_equal 'foo.bar', vite_env['VITE_RUBY_MODE']
72
+ assert_equal '/baz', vite_env['VITE_RUBY_ROOT']
73
+ ensure
74
+ ENV.delete('VITE_RUBY_MODE')
75
+ ENV.delete('VITE_RUBY_ROOT')
71
76
  end
72
77
  end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class CommandsTest < ViteRails::Test
6
+ def stub_builder(stale:, build_with_vite:)
7
+ ViteRails.builder.stub :stale?, stale do
8
+ ViteRails.builder.stub :build_with_vite, build_with_vite do
9
+ yield
10
+ end
11
+ end
12
+ end
13
+
14
+ def test_bootstrap
15
+ assert ViteRails.bootstrap
16
+ end
17
+
18
+ def test_build_returns_success_status_when_stale
19
+ stub_builder(stale: true, build_with_vite: true) {
20
+ assert_equal true, ViteRails.build
21
+ assert_equal true, ViteRails.build_from_rake
22
+ }
23
+ end
24
+
25
+ def test_build_returns_success_status_when_fresh
26
+ stub_builder(stale: false, build_with_vite: true) {
27
+ assert_equal true, ViteRails.build
28
+ assert_equal true, ViteRails.build_from_rake
29
+ }
30
+ end
31
+
32
+ def test_build_returns_failure_status_when_stale
33
+ stub_builder(stale: true, build_with_vite: false) {
34
+ assert_equal false, ViteRails.build
35
+ }
36
+ end
37
+
38
+ def test_clean
39
+ with_rails_env('test') { |config|
40
+ manifest = config.build_output_dir.join('manifest.json')
41
+
42
+ # Should not clean, the manifest does not exist.
43
+ config.build_output_dir.mkdir unless config.build_output_dir.exist?
44
+ refute ViteRails.clean
45
+
46
+ # Should not clean, the file is recent.
47
+ manifest.write('{}')
48
+ assert ViteRails.clean_from_rake(OpenStruct.new)
49
+ assert manifest.exist?
50
+
51
+ # Should clean if we remove age restrictions.
52
+ assert ViteRails.clean(keep_up_to: 0, age_in_seconds: 0)
53
+ assert config.build_output_dir.exist?
54
+ refute manifest.exist?
55
+ }
56
+ end
57
+
58
+ def test_clobber
59
+ with_rails_env('test') { |config|
60
+ config.build_output_dir.mkdir unless config.build_output_dir.exist?
61
+ config.build_output_dir.join('manifest.json').write('{}')
62
+ assert config.build_output_dir.exist?
63
+ ViteRails.clobber
64
+ refute config.build_output_dir.exist?
65
+ }
66
+ end
67
+ end
@@ -3,78 +3,120 @@
3
3
  require 'test_helper'
4
4
 
5
5
  class ConfigurationTest < ViteRails::Test
6
- def setup
7
- @config = ViteRails::Configuration.new(
8
- root_path: Pathname.new(File.expand_path('test_app', __dir__)),
9
- config_path: Pathname.new(File.expand_path('./test_app/config/vite.yml', __dir__)),
10
- env: 'production',
11
- )
6
+ def expand_path(path)
7
+ File.expand_path(Pathname.new(__dir__).join(path).to_s)
8
+ end
9
+
10
+ def assert_path(expected, actual)
11
+ assert_equal expand_path(expected), actual.to_s
12
12
  end
13
13
 
14
- def test_source_path
15
- source_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/app/javascript').to_s
16
- assert_equal source_path, @config.source_path.to_s
14
+ def assert_pathname(expected, actual)
15
+ assert_equal Pathname.new(expand_path("test_app/#{ expected }")), actual
17
16
  end
18
17
 
19
- def test_source_entry_path
20
- source_entry_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/app/javascript', 'packs').to_s
21
- assert_equal @config.source_entry_path.to_s, source_entry_path
18
+ def resolve_config(mode: 'production', root: test_app_path, **attrs)
19
+ ViteRails::Config.resolve_config(mode: mode, root: root, **attrs)
22
20
  end
23
21
 
24
- def test_public_root_path
25
- public_root_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/public').to_s
26
- assert_equal @config.public_path.to_s, public_root_path
22
+ def setup
23
+ @config = resolve_config
27
24
  end
28
25
 
29
- def test_public_output_path
30
- public_output_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/public/packs').to_s
31
- assert_equal @config.public_output_path.to_s, public_output_path
26
+ def test_source_code_dir
27
+ assert_path 'test_app/app/frontend', @config.source_code_dir
28
+ end
32
29
 
33
- @config = ViteRails::Configuration.new(
34
- root_path: @config.root_path,
35
- config_path: Pathname.new(File.expand_path('./test_app/config/vite_public_root.yml', __dir__)),
36
- env: 'production',
37
- )
30
+ def test_entrypoints_dir
31
+ assert_path 'test_app/app/frontend/entrypoints', @config.resolved_entrypoints_dir
32
+ end
38
33
 
39
- public_output_path = File.expand_path File.join(File.dirname(__FILE__), 'public/packs').to_s
40
- assert_equal @config.public_output_path.to_s, public_output_path
34
+ def test_public_dir
35
+ assert_path 'test_app/public', @config.public_dir
41
36
  end
42
37
 
43
- def test_public_manifest_path
44
- public_manifest_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/public/packs', 'manifest.json').to_s
45
- assert_equal @config.public_manifest_path.to_s, public_manifest_path
38
+ def test_build_output_dir
39
+ assert_path 'test_app/public/vite-production', @config.build_output_dir
40
+
41
+ @config = resolve_config(config_path: 'config/vite_public_dir.json')
42
+ assert_path 'public/vite', @config.build_output_dir
46
43
  end
47
44
 
48
- def test_cache_path
49
- cache_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/tmp/cache/vite').to_s
50
- assert_equal @config.cache_path.to_s, cache_path
45
+ def test_manifest_path
46
+ assert_path 'test_app/public/vite-production/manifest.json', @config.manifest_path
51
47
  end
52
48
 
53
- def test_additional_paths
54
- assert_equal @config.additional_paths, ['app/assets', '/etc/yarn', 'some.config.js', 'app/elm']
49
+ def test_build_cache_dir
50
+ assert_path 'test_app/tmp/cache/vite', @config.build_cache_dir
55
51
  end
56
52
 
57
- def test_cache_manifest?
58
- assert @config.cache_manifest?
53
+ def test_watch_additional_paths
54
+ assert_equal [], @config.watch_additional_paths
55
+ @config = resolve_config(config_path: 'config/vite_additional_paths.json')
56
+ assert_equal ['config/*'], @config.watch_additional_paths
57
+ end
59
58
 
60
- with_rails_env('development') do
61
- refute ViteRails.config.cache_manifest?
59
+ def test_auto_build
60
+ refute @config.auto_build
61
+
62
+ with_rails_env('development') do |config|
63
+ assert config.auto_build
64
+ end
65
+
66
+ with_rails_env('test') do |config|
67
+ assert config.auto_build
62
68
  end
63
69
 
64
- with_rails_env('test') do
65
- refute ViteRails.config.cache_manifest?
70
+ with_rails_env('staging') do |config|
71
+ refute config.auto_build
66
72
  end
67
73
  end
68
74
 
69
- def test_compile?
70
- refute @config.compile?
75
+ def test_protocol
76
+ assert_equal 'http', @config.protocol
77
+ end
71
78
 
72
- with_rails_env('development') do
73
- assert ViteRails.config.compile?
74
- end
79
+ def test_host_with_port
80
+ assert_equal 3036, @config.port
75
81
 
76
- with_rails_env('test') do
77
- assert ViteRails.config.compile?
82
+ with_rails_env('development') do |config|
83
+ assert_equal 3535, config.port
84
+ assert_equal 'localhost:3535', config.host_with_port
78
85
  end
79
86
  end
87
+
88
+ def test_environment_vars
89
+ ViteRails.env = {
90
+ 'VITE_RUBY_AUTO_BUILD' => 'true',
91
+ 'VITE_RUBY_HOST' => 'example.com',
92
+ 'VITE_RUBY_PORT' => '1920',
93
+ 'VITE_RUBY_HTTPS' => 'true',
94
+ 'VITE_RUBY_CONFIG_PATH' => 'config/vite_additional_paths.json',
95
+ 'VITE_RUBY_BUILD_CACHE_DIR' => 'tmp/vitebuild',
96
+ 'VITE_RUBY_PUBLIC_DIR' => 'pb',
97
+ 'VITE_RUBY_PUBLIC_OUTPUT_DIR' => 'ft',
98
+ 'VITE_RUBY_ASSETS_DIR' => 'as',
99
+ 'VITE_RUBY_SOURCE_CODE_DIR' => 'app',
100
+ 'VITE_RUBY_ENTRYPOINTS_DIR' => 'frontend/entrypoints',
101
+ 'VITE_RUBY_HIDE_BUILD_CONSOLE_OUTPUT' => 'true',
102
+ }
103
+ @config = resolve_config
104
+ assert_equal true, @config.auto_build
105
+ assert_equal 'example.com', @config.host
106
+ assert_equal 1920, @config.port
107
+ assert_equal true, @config.https
108
+ assert_equal 'https', @config.protocol
109
+ assert_equal Pathname.new('config/vite_additional_paths.json'), @config.config_path
110
+ assert_pathname 'tmp/vitebuild', @config.build_cache_dir
111
+ assert_pathname 'pb', @config.public_dir
112
+ assert_equal Pathname.new('ft'), @config.public_output_dir
113
+ assert_pathname 'pb/ft', @config.build_output_dir
114
+ assert_equal 'as', @config.assets_dir
115
+ assert_pathname 'app', @config.source_code_dir
116
+ assert_equal 'frontend/entrypoints', @config.entrypoints_dir
117
+ assert_pathname 'app/frontend/entrypoints', @config.resolved_entrypoints_dir
118
+ assert_equal true, @config.hide_build_console_output
119
+ ensure
120
+ ViteRails.env = {}
121
+ end
80
122
  end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class DevServerProxyTest < ViteRails::Test
6
+ include Rack::Test::Methods
7
+
8
+ def app
9
+ # Capture all changes to the env made by the proxy.
10
+ capture_app = Rack::Builder.new.run(->(env) {
11
+ [200, { 'Content-Type' => 'application/json' }, env.to_json]
12
+ })
13
+ # Avoid actually using the proxy.
14
+ Rack::Proxy.define_method(:perform_request) { |env| capture_app.call(env) }
15
+
16
+ ViteRails::DevServerProxy.new(capture_app)
17
+ end
18
+
19
+ def test_non_asset
20
+ get_with_dev_server_running '/'
21
+ assert_not_forwarded
22
+ end
23
+
24
+ def test_non_vite_asset
25
+ get_with_dev_server_running '/example_import.js'
26
+ assert_not_forwarded
27
+ end
28
+
29
+ def test_vite_asset
30
+ get_with_dev_server_running '/vite-production/application.js'
31
+ assert_forwarded to: '/application.js'
32
+ end
33
+
34
+ def test_vite_client
35
+ get_with_dev_server_running '/@vite/client'
36
+ assert_forwarded to: '/@vite/client'
37
+ end
38
+
39
+ def test_vite_import
40
+ get_with_dev_server_running '/@fs//package/example/app/frontend/App.vue?import&t=1611322300214&vue&type=style&index=0&lang.css'
41
+ assert_forwarded to: '/@fs//package/example/app/frontend/App.vue?import&t=1611322300214&vue&type=style&index=0&lang.css'
42
+ end
43
+
44
+ def test_hmr_for_stylesheet
45
+ get_with_dev_server_running '/colored.css?t=1611322562923'
46
+ assert_forwarded to: '/colored.css?t=1611322562923'
47
+ end
48
+
49
+ def test_hmr_for_imported_entrypoint
50
+ get_with_dev_server_running '/colored.css?import&t=1611322562923'
51
+ assert_forwarded to: '/colored.css?import&t=1611322562923'
52
+ end
53
+
54
+ def test_entrypoint_imported_from_entrypoint
55
+ header 'Referer', 'http://localhost:3000/vite-production/application.js'
56
+ get_with_dev_server_running '/example_import.js'
57
+ assert_forwarded to: '/example_import.js'
58
+ end
59
+
60
+ def test_without_dev_server_running
61
+ get '/vite-production/application.js'
62
+ assert_not_forwarded
63
+
64
+ get '/colored.css?import&t=1611322562923'
65
+ assert_not_forwarded
66
+
67
+ header 'Referer', 'http://localhost:3000/vite-production/application.js'
68
+ get '/example_import.js'
69
+ assert_not_forwarded
70
+ end
71
+
72
+ private
73
+
74
+ def get_with_dev_server_running(*args)
75
+ with_dev_server_running {
76
+ get(*args)
77
+ }
78
+ end
79
+
80
+ def assert_not_forwarded
81
+ assert last_response.ok?
82
+ env = JSON.parse(last_response.body)
83
+ assert_nil env['HTTP_X_FORWARDED_HOST']
84
+ assert_nil env['HTTP_X_FORWARDED_PORT']
85
+ end
86
+
87
+ def assert_forwarded(to: nil)
88
+ assert last_response.ok?
89
+ env = JSON.parse(last_response.body)
90
+
91
+ assert_equal ViteRails.config.host, env['HTTP_X_FORWARDED_HOST']
92
+ assert_equal ViteRails.config.port, Integer(env['HTTP_X_FORWARDED_PORT'])
93
+
94
+ return unless to
95
+
96
+ path, query = to.split('?')
97
+ assert_equal path, env['PATH_INFO']
98
+ assert_equal query, env['QUERY_STRING']
99
+ assert_equal to, env['REQUEST_URI']
100
+ end
101
+ end