vite_rails 1.0.7 → 1.0.12

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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/CONTRIBUTING.md +0 -1
  4. data/README.md +34 -8
  5. data/lib/install/config/vite.config.ts +0 -3
  6. data/lib/install/javascript/entrypoints/application.js +8 -4
  7. data/lib/install/template.rb +3 -3
  8. data/lib/tasks/vite/build.rake +12 -6
  9. data/lib/tasks/vite/clean.rake +1 -3
  10. data/lib/tasks/vite/install_dependencies.rake +3 -9
  11. data/lib/tasks/vite/verify_install.rake +3 -3
  12. data/lib/vite_rails.rb +23 -34
  13. data/lib/vite_rails/builder.rb +11 -13
  14. data/lib/vite_rails/commands.rb +51 -10
  15. data/lib/vite_rails/config.rb +70 -35
  16. data/lib/vite_rails/dev_server_proxy.rb +26 -18
  17. data/lib/vite_rails/helper.rb +14 -10
  18. data/lib/vite_rails/manifest.rb +27 -22
  19. data/lib/vite_rails/runner.rb +3 -6
  20. data/lib/vite_rails/version.rb +1 -1
  21. data/package.json +9 -2
  22. data/package/default.vite.json +2 -1
  23. data/test/builder_test.rb +27 -22
  24. data/test/commands_test.rb +67 -0
  25. data/test/config_test.rb +133 -0
  26. data/test/dev_server_proxy_test.rb +102 -0
  27. data/test/dev_server_test.rb +0 -30
  28. data/test/engine_rake_tasks_test.rb +56 -17
  29. data/test/helper_test.rb +40 -103
  30. data/test/manifest_test.rb +39 -29
  31. data/test/mode_test.rb +6 -11
  32. data/test/mounted_app/test/dummy/config/vite.json +5 -11
  33. data/test/mounted_app/test/dummy/package.json +5 -4
  34. data/test/mounted_app/test/dummy/yarn.lock +208 -0
  35. data/test/rake_tasks_test.rb +7 -21
  36. data/test/runner_test.rb +31 -0
  37. data/test/test_app/app/frontend/entrypoints/application.js +2 -0
  38. data/test/test_app/config/vite.json +0 -2
  39. data/test/test_app/config/vite_additional_paths.json +5 -0
  40. data/test/test_app/config/vite_public_dir.json +5 -0
  41. data/test/test_app/public/vite-production/manifest-assets.json +10 -0
  42. data/test/test_app/public/vite-production/manifest.json +39 -0
  43. data/test/test_helper.rb +48 -14
  44. metadata +25 -25
  45. data/test/command_test.rb +0 -35
  46. data/test/configuration_test.rb +0 -80
  47. data/test/dev_server_runner_test.rb +0 -83
  48. data/test/test_app/app/javascript/entrypoints/application.js +0 -10
  49. data/test/test_app/app/javascript/entrypoints/multi_entry.css +0 -4
  50. data/test/test_app/app/javascript/entrypoints/multi_entry.js +0 -4
  51. data/test/test_app/config/vite_public_root.yml +0 -20
  52. data/test/test_app/public/vite/manifest.json +0 -36
  53. data/test/vite_runner_test.rb +0 -59
  54. data/test/webpacker_test.rb +0 -15
@@ -1,4 +1,5 @@
1
1
  {
2
+ "assetHost": null,
2
3
  "assetsDir": "assets",
3
4
  "autoBuild": false,
4
5
  "buildCacheDir": "tmp/cache/vite",
@@ -6,7 +7,7 @@
6
7
  "configPath": "config/vite.json",
7
8
  "publicDir": "public",
8
9
  "entrypointsDir": "entrypoints",
9
- "sourceCodeDir": "app/javascript",
10
+ "sourceCodeDir": "app/frontend",
10
11
  "host": "localhost",
11
12
  "https": null,
12
13
  "port": 3036,
@@ -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.config.to_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
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class ConfigTest < ViteRails::Test
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
+ end
13
+
14
+ def assert_pathname(expected, actual)
15
+ assert_equal Pathname.new(expand_path("test_app/#{ expected }")), actual
16
+ end
17
+
18
+ def resolve_config(mode: 'production', root: test_app_path, **attrs)
19
+ ViteRails::Config.resolve_config(mode: mode, root: root, **attrs)
20
+ end
21
+
22
+ def setup
23
+ @config = resolve_config
24
+ end
25
+
26
+ def test_source_code_dir
27
+ assert_equal 'app/frontend', @config.source_code_dir
28
+ end
29
+
30
+ def test_entrypoints_dir
31
+ assert_path 'test_app/app/frontend/entrypoints', @config.resolved_entrypoints_dir
32
+ end
33
+
34
+ def test_public_dir
35
+ assert_equal 'public', @config.public_dir
36
+ end
37
+
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
43
+ end
44
+
45
+ def test_manifest_path
46
+ assert_path 'test_app/public/vite-production/manifest.json', @config.manifest_path
47
+ end
48
+
49
+ def test_build_cache_dir
50
+ assert_path 'test_app/tmp/cache/vite', @config.build_cache_dir
51
+ end
52
+
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
58
+
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
68
+ end
69
+
70
+ with_rails_env('staging') do |config|
71
+ refute config.auto_build
72
+ end
73
+ end
74
+
75
+ def test_protocol
76
+ assert_equal 'http', @config.protocol
77
+ end
78
+
79
+ def test_host_with_port
80
+ assert_equal 3036, @config.port
81
+
82
+ with_rails_env('development') do |config|
83
+ assert_equal 3535, config.port
84
+ assert_equal 'localhost:3535', config.host_with_port
85
+ end
86
+ end
87
+
88
+ def test_to_env
89
+ env = @config.to_env
90
+ assert_nil env['VITE_RUBY_ASSET_HOST']
91
+
92
+ Rails.application.config.action_controller.asset_host = 'assets-cdn.com'
93
+ env = refresh_config.to_env
94
+ assert_equal env['VITE_RUBY_ASSET_HOST'], 'assets-cdn.com'
95
+ ensure
96
+ Rails.application.config.action_controller.asset_host = nil
97
+ end
98
+
99
+ def test_environment_vars
100
+ ViteRails.env = {
101
+ 'VITE_RUBY_AUTO_BUILD' => 'true',
102
+ 'VITE_RUBY_HOST' => 'example.com',
103
+ 'VITE_RUBY_PORT' => '1920',
104
+ 'VITE_RUBY_HTTPS' => 'true',
105
+ 'VITE_RUBY_CONFIG_PATH' => 'config/vite_additional_paths.json',
106
+ 'VITE_RUBY_BUILD_CACHE_DIR' => 'tmp/vitebuild',
107
+ 'VITE_RUBY_PUBLIC_DIR' => 'pb',
108
+ 'VITE_RUBY_PUBLIC_OUTPUT_DIR' => 'ft',
109
+ 'VITE_RUBY_ASSETS_DIR' => 'as',
110
+ 'VITE_RUBY_SOURCE_CODE_DIR' => 'app',
111
+ 'VITE_RUBY_ENTRYPOINTS_DIR' => 'frontend/entrypoints',
112
+ 'VITE_RUBY_HIDE_BUILD_CONSOLE_OUTPUT' => 'true',
113
+ }
114
+ @config = resolve_config
115
+ assert_equal true, @config.auto_build
116
+ assert_equal 'example.com', @config.host
117
+ assert_equal 1920, @config.port
118
+ assert_equal true, @config.https
119
+ assert_equal 'https', @config.protocol
120
+ assert_equal 'config/vite_additional_paths.json', @config.config_path
121
+ assert_pathname 'tmp/vitebuild', @config.build_cache_dir
122
+ assert_equal 'pb', @config.public_dir
123
+ assert_equal 'ft', @config.public_output_dir
124
+ assert_pathname 'pb/ft', @config.build_output_dir
125
+ assert_equal 'as', @config.assets_dir
126
+ assert_equal 'app', @config.source_code_dir
127
+ assert_equal 'frontend/entrypoints', @config.entrypoints_dir
128
+ assert_pathname 'app/frontend/entrypoints', @config.resolved_entrypoints_dir
129
+ assert_equal true, @config.hide_build_console_output
130
+ ensure
131
+ ViteRails.env = {}
132
+ end
133
+ end
@@ -0,0 +1,102 @@
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.remove_method(:perform_request)
15
+ Rack::Proxy.define_method(:perform_request) { |env| capture_app.call(env) }
16
+
17
+ ViteRails::DevServerProxy.new(capture_app)
18
+ end
19
+
20
+ def test_non_asset
21
+ get_with_dev_server_running '/'
22
+ assert_not_forwarded
23
+ end
24
+
25
+ def test_non_vite_asset
26
+ get_with_dev_server_running '/example_import.js'
27
+ assert_not_forwarded
28
+ end
29
+
30
+ def test_vite_asset
31
+ get_with_dev_server_running '/vite-production/application.js'
32
+ assert_forwarded to: '/application.js'
33
+ end
34
+
35
+ def test_vite_client
36
+ get_with_dev_server_running '/@vite/client'
37
+ assert_forwarded to: '/@vite/client'
38
+ end
39
+
40
+ def test_vite_import
41
+ get_with_dev_server_running '/@fs//package/example/app/frontend/App.vue?import&t=1611322300214&vue&type=style&index=0&lang.css'
42
+ assert_forwarded to: '/@fs//package/example/app/frontend/App.vue?import&t=1611322300214&vue&type=style&index=0&lang.css'
43
+ end
44
+
45
+ def test_hmr_for_stylesheet
46
+ get_with_dev_server_running '/colored.css?t=1611322562923'
47
+ assert_forwarded to: '/colored.css?t=1611322562923'
48
+ end
49
+
50
+ def test_hmr_for_imported_entrypoint
51
+ get_with_dev_server_running '/colored.css?import&t=1611322562923'
52
+ assert_forwarded to: '/colored.css?import&t=1611322562923'
53
+ end
54
+
55
+ def test_entrypoint_imported_from_entrypoint
56
+ header 'Referer', 'http://localhost:3000/vite-production/application.js'
57
+ get_with_dev_server_running '/example_import.js'
58
+ assert_forwarded to: '/example_import.js'
59
+ end
60
+
61
+ def test_without_dev_server_running
62
+ get '/vite-production/application.js'
63
+ assert_not_forwarded
64
+
65
+ get '/colored.css?import&t=1611322562923'
66
+ assert_not_forwarded
67
+
68
+ header 'Referer', 'http://localhost:3000/vite-production/application.js'
69
+ get '/example_import.js'
70
+ assert_not_forwarded
71
+ end
72
+
73
+ private
74
+
75
+ def get_with_dev_server_running(*args)
76
+ with_dev_server_running {
77
+ get(*args)
78
+ }
79
+ end
80
+
81
+ def assert_not_forwarded
82
+ assert last_response.ok?
83
+ env = JSON.parse(last_response.body)
84
+ assert_nil env['HTTP_X_FORWARDED_HOST']
85
+ assert_nil env['HTTP_X_FORWARDED_PORT']
86
+ end
87
+
88
+ def assert_forwarded(to: nil)
89
+ assert last_response.ok?
90
+ env = JSON.parse(last_response.body)
91
+
92
+ assert_equal ViteRails.config.host, env['HTTP_X_FORWARDED_HOST']
93
+ assert_equal ViteRails.config.port, Integer(env['HTTP_X_FORWARDED_PORT'])
94
+
95
+ return unless to
96
+
97
+ path, query = to.split('?')
98
+ assert_equal path, env['PATH_INFO']
99
+ assert_equal query.to_s, env['QUERY_STRING'].to_s
100
+ assert_equal to, env['REQUEST_URI']
101
+ end
102
+ end
@@ -6,34 +6,4 @@ class DevServerTest < ViteRails::Test
6
6
  def test_running?
7
7
  refute ViteRails.dev_server.running?
8
8
  end
9
-
10
- def test_host
11
- with_rails_env('development') do
12
- assert_equal ViteRails.config.host, 'localhost'
13
- end
14
- end
15
-
16
- def test_port
17
- with_rails_env('development') do
18
- assert_equal ViteRails.config.port, 3035
19
- end
20
- end
21
-
22
- def test_https?
23
- with_rails_env('development') do
24
- assert_equal ViteRails.config.https, false
25
- end
26
- end
27
-
28
- def test_protocol
29
- with_rails_env('development') do
30
- assert_equal ViteRails.config.protocol, 'http'
31
- end
32
- end
33
-
34
- def test_host_with_port
35
- with_rails_env('development') do
36
- assert_equal ViteRails.config.host_with_port, 'localhost:3035'
37
- end
38
- end
39
9
  end
@@ -4,39 +4,78 @@ require 'test_helper'
4
4
 
5
5
  class EngineRakeTasksTest < Minitest::Test
6
6
  def setup
7
- remove_vite_binstubs
7
+ remove_vite_files
8
8
  end
9
9
 
10
10
  def teardown
11
- remove_vite_binstubs
11
+ remove_vite_files
12
12
  end
13
13
 
14
- def test_task_mounted
15
- output = Dir.chdir(mounted_app_path) { `rake -T` }
14
+ def test_tasks_mounted
15
+ output = within_mounted_app { `bundle exec rake -T` }
16
16
  assert_includes output, 'app:vite'
17
17
  end
18
18
 
19
- def test_binstubs
20
- Dir.chdir(mounted_app_path) { `bundle exec rake app:vite:binstubs` }
21
- vite_binstub_paths.each { |path| assert File.exist?(path) }
19
+ def test_rake_tasks
20
+ within_mounted_app { `bundle exec rake app:vite:binstubs` }
21
+ assert vite_binstub_path.exist?
22
+
23
+ within_mounted_app { `bundle exec rake app:vite:install` }
24
+ assert vite_config_ts_path.exist?
25
+ assert app_frontend_dir.exist?
26
+
27
+ within_mounted_app { `bundle exec rake app:vite:build` }
28
+ assert app_public_dir.exist?
29
+ assert app_public_dir.join('manifest.json').exist?
30
+ assert app_public_dir.join('assets').exist?
31
+
32
+ within_mounted_app { `bundle exec rake app:vite:clean` }
33
+ assert app_public_dir.join('manifest.json').exist? # Still fresh
34
+
35
+ within_mounted_app { `bundle exec rake app:vite:clean[0,0]` }
36
+ refute app_public_dir.join('manifest.json').exist?
37
+
38
+ within_mounted_app { `bundle exec rake app:vite:clobber` }
39
+ refute app_public_dir.exist?
40
+ rescue Minitest::Assertion => error
41
+ raise error, [error.message, @command_results.join("\n\n")].join("\n")
22
42
  end
23
43
 
24
44
  private
25
45
 
46
+ def within_mounted_app
47
+ Dir.chdir(mounted_app_path) { yield }.tap { |result| @command_results << result }
48
+ end
49
+
26
50
  def mounted_app_path
27
- File.expand_path('mounted_app', __dir__)
51
+ Pathname.new(File.expand_path(__dir__)).join('mounted_app')
52
+ end
53
+
54
+ def root_dir
55
+ mounted_app_path.join('test/dummy')
56
+ end
57
+
58
+ def vite_binstub_path
59
+ root_dir.join('bin/vite')
60
+ end
61
+
62
+ def vite_config_ts_path
63
+ root_dir.join('vite.config.ts')
64
+ end
65
+
66
+ def app_frontend_dir
67
+ root_dir.join('app/frontend')
28
68
  end
29
69
 
30
- def vite_binstub_paths
31
- [
32
- "#{ mounted_app_path }/test/dummy/bin/vite",
33
- "#{ mounted_app_path }/test/dummy/bin/vite-dev-server",
34
- ]
70
+ def app_public_dir
71
+ root_dir.join('public/vite-dev')
35
72
  end
36
73
 
37
- def remove_vite_binstubs
38
- vite_binstub_paths.each do |path|
39
- File.delete(path) if File.exist?(path)
40
- end
74
+ def remove_vite_files
75
+ vite_binstub_path.delete if vite_binstub_path.exist?
76
+ vite_config_ts_path.delete if vite_config_ts_path.exist?
77
+ app_frontend_dir.rmtree if app_frontend_dir.exist?
78
+ app_public_dir.rmtree if app_public_dir.exist?
79
+ @command_results = []
41
80
  end
42
81
  end