diff --git a/package.json b/package.json
index 3d86088f..9f53874f 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,5 @@
"type": "git",
"url": "https://github.com/ElMassimo/vite_ruby"
},
- "homepage": "https://github.com/ElMassimo/vite_ruby",
- "packageManager": "pnpm@10.32.1"
+ "homepage": "https://github.com/ElMassimo/vite_ruby"
}
\ No newline at end of file
diff --git a/test/helper_test.rb b/test/helper_test.rb
index 27686bc8..40131045 100644
--- a/test/helper_test.rb
+++ b/test/helper_test.rb
@@ -42,6 +42,11 @@ def with_dev_server_running(&block)
refresh_config(mode: "development")
super
end
+
+ def with_skip_proxy_dev_server_running(&block)
+ refresh_config(mode: "development", skip_proxy: true)
+ ViteRuby.instance.stub(:dev_server_running?, true, &block)
+ end
end
class LegacyHelperTest < HelperTestCase
@@ -190,6 +195,82 @@ def test_vite_image_tag
}
end
+ # skipProxy tests: validate that all tag helpers emit absolute URLs pointing
+ # directly to the Vite dev server when skipProxy is enabled.
+
+ def test_vite_client_tag_with_skip_proxy
+ assert_nil vite_client_tag
+ with_skip_proxy_dev_server_running {
+ origin = ViteRuby.config.origin
+ assert_equal %(), vite_client_tag
+ }
+ end
+
+ def test_vite_asset_path_with_skip_proxy
+ with_skip_proxy_dev_server_running {
+ origin = ViteRuby.config.origin
+ assert_equal "#{origin}/vite-dev/entrypoints/main.ts", vite_asset_path("main.ts")
+ assert_equal "#{origin}/vite-dev/entrypoints/app.css", vite_asset_path("app.css")
+ assert_equal "#{origin}/vite-dev/images/logo.png", vite_asset_path("images/logo.png")
+ }
+ end
+
+ def test_vite_javascript_tag_with_skip_proxy
+ with_skip_proxy_dev_server_running {
+ origin = ViteRuby.config.origin
+ assert_equal %(),
+ vite_typescript_tag("main")
+
+ assert_equal %(),
+ vite_javascript_tag("entrypoints/frameworks/vue")
+ }
+ end
+
+ def test_vite_stylesheet_tag_with_skip_proxy
+ with_skip_proxy_dev_server_running {
+ origin = ViteRuby.config.origin
+ assert_similar link(href: "#{origin}/vite-dev/entrypoints/app.css"), vite_stylesheet_tag("app")
+ assert_equal vite_stylesheet_tag("app"), vite_stylesheet_tag("app.css")
+
+ if Rails::VERSION::MAJOR >= 7
+ assert_similar link(href: "#{origin}/vite-dev/entrypoints/sassy.scss"), vite_stylesheet_tag("sassy.scss")
+ else
+ # Rails 6 appends .css to non-.css extensions. Without the proxy to
+ # normalize .scss.css → .scss, Vite cannot serve this URL.
+ assert_similar link(href: "#{origin}/vite-dev/entrypoints/sassy.scss.css"), vite_stylesheet_tag("sassy.scss")
+ end
+ }
+ end
+
+ def test_vite_image_tag_with_skip_proxy
+ with_skip_proxy_dev_server_running {
+ origin = ViteRuby.config.origin
+ assert_equal %(
),
+ vite_image_tag("images/logo.png", alt: "Logo")
+
+ assert_equal %(
),
+ vite_image_tag("images/logo.png", srcset: {"images/logo-2x.png" => "2x"}, alt: "Logo")
+ }
+ end
+
+ def test_vite_react_refresh_tag_with_skip_proxy
+ with_skip_proxy_dev_server_running {
+ origin = ViteRuby.config.origin
+ assert_equal <<~HTML.chomp, vite_react_refresh_tag(nonce: nil)
+
+ HTML
+ }
+ end
+
def test_vite_picture_tag
if Rails.gem_version >= Gem::Version.new("7.1.0")
assert_equal <<~HTML.gsub(/\n\s*/, ""), vite_picture_tag("images/logo.svg", "images/logo.png", class: "test", image: {alt: "Logo"})
diff --git a/test/manifest_test.rb b/test/manifest_test.rb
index b777c750..1c2a8870 100644
--- a/test/manifest_test.rb
+++ b/test/manifest_test.rb
@@ -193,6 +193,73 @@ def test_vite_client_src
}
end
+ # NOTE: skipProxy (experimental since v3.2.12) causes asset URLs to point
+ # directly to the Vite dev server. Known caveats:
+ #
+ # 1. CORS: Browser makes cross-origin requests to Vite. Vite sets permissive
+ # CORS headers by default, but custom middleware may interfere.
+ # 2. Rails 6 .scss.css: Without the proxy to normalize .scss.css → .scss,
+ # Rails 6's stylesheet_link_tag produces URLs Vite can't serve.
+ # 3. Cookies: Asset requests to a different origin won't carry same-origin
+ # cookies. Usually not an issue since assets don't require auth.
+ # 4. SSL: Both Rails and Vite need valid certs when using HTTPS.
+ # 5. Docker/VM: "localhost:3036" from the browser may not reach Vite inside
+ # a container. Must configure host to a reachable address.
+ # 6. vite_asset_url may produce double-origin URLs since path_for already
+ # returns an absolute URL when skipProxy is enabled.
+
+ def test_lookup_success_with_skip_proxy_and_dev_server_running
+ refresh_config(mode: "development", skip_proxy: true)
+ with_dev_server_running {
+ origin = ViteRuby.config.origin # "https://localhost:3535"
+
+ entry = {"file" => "#{origin}/vite-dev/entrypoints/application.js"}
+ assert_equal entry, lookup!("application.js", type: :javascript)
+ assert_equal entry, lookup!("entrypoints/application.js")
+
+ assert_equal "#{origin}/vite-dev/entrypoints/application.ts",
+ path_for("application", type: :typescript)
+
+ assert_equal "#{origin}/vite-dev/entrypoints/styles.css",
+ path_for("styles", type: :stylesheet)
+
+ assert_equal "#{origin}/vite-dev/image/logo.png",
+ path_for("image/logo.png")
+
+ assert_equal "#{origin}/vite-dev/logo.png",
+ path_for("~/logo.png")
+
+ assert_equal "#{origin}/vite-dev/@fs#{ViteRuby.config.root}/app/assets/theme.css",
+ path_for("/app/assets/theme", type: :stylesheet)
+ }
+ end
+
+ def test_vite_client_src_with_skip_proxy
+ refresh_config(mode: "development", skip_proxy: true)
+
+ assert_nil vite_client_src
+
+ with_dev_server_running {
+ assert_equal "#{ViteRuby.config.origin}/vite-dev/@vite/client", vite_client_src
+ }
+
+ # Origin from skip_proxy takes precedence over asset_host
+ refresh_config(asset_host: "http://example.com", mode: "development", skip_proxy: true)
+
+ with_dev_server_running {
+ assert_equal "#{ViteRuby.config.origin}/vite-dev/@vite/client", vite_client_src
+ }
+ end
+
+ def test_skip_proxy_has_no_effect_without_dev_server
+ refresh_config(skip_proxy: true)
+
+ # Production paths are unchanged — skipProxy only matters when dev server runs
+ assert_equal prefixed("main.9dcad042.js"), path_for("main", type: :typescript)
+ assert_equal prefixed("app.517bf154.css"), path_for("app", type: :stylesheet)
+ assert_equal prefixed("logo.f42fb7ea.png"), path_for("images/logo.png")
+ end
+
def test_lookup_nil
assert_nil lookup("foo.js")
end