diff --git a/CHANGELOG.md b/CHANGELOG.md index 832b232..087c415 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - Preserve both the protocol error and `error_details` in `Page.expect_screenshot/2` errors as `{:error, {error, error_details}}`. #58 +### Fixed +- Launch JavaScript Playwright CLI files through Node on Windows or when `PLAYWRIGHT_NODEJS_PATH` is configured, while preserving shebang execution on Unix. + ### Removed - Support for the Playwright 1.60 expectation response format. #58 diff --git a/lib/playwright_ex/processes/port_transport.ex b/lib/playwright_ex/processes/port_transport.ex index b18917d..ef729f5 100644 --- a/lib/playwright_ex/processes/port_transport.ex +++ b/lib/playwright_ex/processes/port_transport.ex @@ -31,9 +31,13 @@ defmodule PlaywrightEx.PortTransport do Start the PortTransport and link it to the connection process. """ def start_link(opts) do - opts = Keyword.validate!(opts, [:executable, :name, :connection_name, env: %{}]) + opts = + opts + |> Keyword.validate!([:executable, :name, :connection_name, env: %{}]) + |> Keyword.update!(:executable, &Path.expand/1) + name = Keyword.get(opts, :name, @default_name) - check_version(opts[:executable]) + check_version(opts[:executable], opts[:env]) GenServer.start_link(__MODULE__, Map.new(opts), name: name) end @@ -44,8 +48,15 @@ defmodule PlaywrightEx.PortTransport do @impl GenServer def init(%{executable: executable, env: env} = opts) do + {command, args} = executable_command(executable, ["run-driver"], env) env = Enum.map(env, fn {k, v} -> {String.to_charlist(k), String.to_charlist(v)} end) - port = Port.open({:spawn_executable, executable}, [:binary, :stderr_to_stdout, args: ["run-driver"], env: env]) + + port = + Port.open( + {:spawn_executable, String.to_charlist(command)}, + [:binary, :stderr_to_stdout, args: args, env: env] + ) + connection_name = Map.get(opts, :connection_name, Connection) {:ok, %__MODULE__{port: port, connection_name: connection_name}} end @@ -108,8 +119,9 @@ defmodule PlaywrightEx.PortTransport do |> Map.update(:method, nil, &Serialization.underscore/1) end - defp check_version(executable) do - {"Version " <> version, 0} = executable |> Path.expand() |> System.cmd(~w(--version)) + defp check_version(executable, env) do + {command, args} = executable_command(executable, ["--version"], env) + {"Version " <> version, 0} = System.cmd(command, args) version = version |> String.trim() |> Version.parse!() recommended = PlaywrightEx.recommended_min_version() @@ -117,4 +129,26 @@ defmodule PlaywrightEx.PortTransport do IO.warn("Playwright version #{version} is below recommended #{recommended}") end end + + defp executable_command(executable, args, env) do + if javascript_file?(executable) and (windows?() or not is_nil(node_override(env))) do + {node_executable!(env), [executable | args]} + else + {executable, args} + end + end + + defp javascript_file?(executable), do: String.downcase(Path.extname(executable)) == ".js" + + defp windows?, do: :os.type() == {:win32, :nt} + + defp node_executable!(env) do + node_override(env) || + System.find_executable("node") || + raise "Node.js executable not found; set PLAYWRIGHT_NODEJS_PATH or add node to PATH" + end + + defp node_override(env) do + Map.get(env, "PLAYWRIGHT_NODEJS_PATH") || System.get_env("PLAYWRIGHT_NODEJS_PATH") + end end