vite_rails 1.0.7 → 1.0.12

Sign up to get free protection for your applications and to get access to all the features.
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