Current section
Files
Jump to
Current section
Files
lib/phoenix_test/playwright/config.ex
screenshot_opts_schema = [
full_page: [type: :boolean, default: true],
omit_background: [type: :boolean, default: false]
]
browsers = ~w(android chromium electron firefox webkit)a
# styler:sort
browser_opts = [
browser: [
default: :chromium,
type: {:in, browsers},
type_doc: "`#{Enum.map_join(browsers, " | ", &":#{&1}")}`"
],
browser_launch_timeout: [
default: to_timeout(second: 4),
type: :non_neg_integer
],
executable_path: [
type: :string,
doc: """
Path to a browser executable to run instead of the bundled one.
Use at your own risk.
"""
],
headless: [
default: true,
type: :boolean
],
slow_mo: [
default: to_timeout(second: 0),
type: :non_neg_integer
]
]
browser_pool_opts =
[
id: [required: true, type: :atom],
size: [required: false, type: :integer, doc: "The default value is `System.schedulers_online() / 2`."]
] ++ browser_opts
playwright_recommended_version = "1.55.0"
# styler:sort
schema_opts = [
accept_dialogs: [
default: true,
type: :boolean,
doc: "Accept browser dialogs (`alert()`, `confirm()`, `prompt()`)."
],
assets_dir: [
default: "./assets",
type_spec: quote(do: binary()),
type_doc: "`t:binary/0`",
type: {:custom, PhoenixTest.Playwright.Config, :__validate_assets_dir__, []},
doc: """
The directory where the JS assets are located and the Playwright CLI is installed.
Playwright version `#{playwright_recommended_version}` or newer is recommended.
"""
],
browser: browser_opts[:browser],
browser_context_opts: [
default: [],
type: {:or, [:map, :keyword_list]},
doc: """
Additional arguments passed to Playwright [Browser.newContext](https://playwright.dev/docs/api/class-browser#browser-new-context).
E.g. `[http_credentials: %{username: "a", password: "b"}]`.
"""
],
browser_launch_timeout: browser_opts[:browser_launch_timeout],
browser_page_opts: [
default: [],
type: {:or, [:map, :keyword_list]},
doc: """
Additional arguments passed to Playwright [Browser.newPage](https://playwright.dev/docs/api/class-browser#browser-new-page).
(E.g. `[accept_downloads: false]`.
"""
],
browser_pool: [
default: :default_pool,
type: :atom,
doc: """
Reuse a browser from this pool instead of launching a new browser per test suite.
"""
],
browser_pool_checkout_timeout: [
default: to_timeout(minute: 1),
type: :non_neg_integer
],
browser_pools: [
required: false,
default: [[id: :default_pool]],
type: {:list, {:non_empty_keyword_list, browser_pool_opts}},
doc: """
Supported keys:
#{NimbleOptions.docs(browser_pool_opts, nest_level: 1)}
"""
],
cli: [
type: {:custom, PhoenixTest.Playwright.Config, :__validate_cli__, []},
deprecated: "Use `assets_dir` instead."
],
ecto_sandbox_stop_owner_delay: [
default: 0,
type: :non_neg_integer,
doc: """
Delay in milliseconds before shutting down the Ecto sandbox owner after a
test ends. Use this to allow LiveViews and other processes in your app
time to stop using database connections before the sandbox owner is
terminated.
"""
],
executable_path: browser_opts[:executable_path],
headless: browser_opts[:headless],
js_logger: [
default: PhoenixTest.Playwright.JsLogger,
type: :atom,
type_doc: "`module | false`",
doc: "`false` to disable, or a module that implements the `PlaywrightEx.JsLogger` behaviour."
],
runner: [
deprecated: """
You can safely remove this option.
`<assets_dir>/node_modules/playwright/cli.js` is now called directly, without needing `npx` or `bunx`.
""",
type: :string
],
screenshot: [
default: false,
type: {:or, [:boolean, non_empty_keyword_list: screenshot_opts_schema]},
type_doc: "`boolean/0 | Keyword.t/0`",
doc: """
Either a boolean or a keyword list:
#{NimbleOptions.docs(screenshot_opts_schema, nest_level: 1)}
"""
],
screenshot_dir: [
default: "screenshots",
type: :string
],
selector_engines: [
default: [],
type: {:or, [:map, :keyword_list]},
doc: """
Define custom Playwright [selector engines](https://playwright.dev/docs/extensibility#custom-selector-engines).
"""
],
slow_mo: browser_opts[:slow_mo],
timeout: [
default: to_timeout(second: 2),
type: :non_neg_integer
],
trace: [
default: false,
type: {:in, [false, true, :open]},
type_doc: "`boolean/0 | :open`"
],
trace_dir: [
default: "traces",
type: :string
]
]
schema = NimbleOptions.new!(schema_opts)
setup_all_keys = ~w(browser_pool browser browser_launch_timeout executable_path headless slow_mo)a
setup_keys = ~w(accept_dialogs ecto_sandbox_stop_owner_delay screenshot trace browser_context_opts browser_page_opts)a
defmodule PhoenixTest.Playwright.Config do
@moduledoc """
Configuration options for the Playwright driver.
Most should be set globally in `config/tests.exs`.
Some can be overridden per test.
All options:
#{NimbleOptions.docs(schema)}
Options that be overridden per test module via the `use PhoenixTest.Playwright.Case` opts:
#{Enum.map_join(setup_all_keys, "\n", &"- `:#{&1}`")}
Options that be overridden per test via ExUnit `@tag`:
#{Enum.map_join(setup_keys, "\n", &"- `:#{&1}`")}
"""
@schema schema
@schema_opts schema_opts
@screenshot_opts_schema screenshot_opts_schema
@setup_all_keys setup_all_keys
@setup_keys setup_keys
@playwright_recommended_version playwright_recommended_version
@doc false
def schema_opts, do: @schema_opts
@doc false
def executable do
[global()[:assets_dir], "node_modules", "playwright", "cli.js"] |> Path.join() |> Path.expand()
end
@doc false
def validate!(config) when is_map(config), do: config |> Keyword.new() |> validate!()
def validate!(config) when is_list(config) do
global()
|> Keyword.merge(config)
|> NimbleOptions.validate!(@schema)
|> normalize()
end
@doc false
def global do
:phoenix_test
|> Application.get_env(:playwright, [])
|> NimbleOptions.validate!(@schema)
|> normalize()
end
@doc false
def global(key), do: Keyword.fetch!(global(), key)
@doc false
def setup_all_keys, do: @setup_all_keys
@doc false
def setup_keys, do: @setup_keys
defp normalize(config), do: Keyword.new(config, fn {key, value} -> {key, normalize(key, value)} end)
defp normalize(:screenshot, true), do: NimbleOptions.validate!([], @screenshot_opts_schema)
defp normalize(_key, value), do: value
def __validate_assets_dir__(assets_dir) do
playwright_json = Path.join([assets_dir, "node_modules", "playwright", "package.json"])
with {:ok, string} <- File.read(playwright_json),
{:ok, json} <- Phoenix.json_library().decode(string) do
version = json["version"] || "0"
if Version.compare(version, @playwright_recommended_version) == :lt do
IO.warn("Playwright version #{version} is below recommended #{@playwright_recommended_version}")
end
{:ok, assets_dir}
else
{:error, error} ->
message = """
could not find playwright in `#{assets_dir}`.
Reason: #{inspect(error)}
To resolve this please
1. Install playwright, e.g. via `npm --prefix assets install playwright`
"""
{:error, message}
end
end
def __validate_cli__(_cli) do
{:error,
"it is deprecated. Use `assets_dir` instead if you want to customize the Playwright installation directory path and remove the `cli` option."}
end
end