From 0eb97b49afff10600e708141117a36162ebfb156 Mon Sep 17 00:00:00 2001 From: Tim Goodwin Date: Thu, 5 Jan 2023 15:33:28 +0000 Subject: [PATCH 1/2] implementing BrowserType.connect_over_cdp/3 --- lib/playwright/browser.ex | 7 +++ lib/playwright/browser_type.ex | 71 ++++++++++++++++++++++++------ lib/playwright/channel/response.ex | 7 +++ 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/lib/playwright/browser.ex b/lib/playwright/browser.ex index 718e65f0..7d0a05c7 100644 --- a/lib/playwright/browser.ex +++ b/lib/playwright/browser.ex @@ -44,6 +44,13 @@ defmodule Playwright.Browser do # API # --------------------------------------------------------------------------- + @spec browser_type(Playwright.Browser.t()) :: {:error, Playwright.Channel.Error.t()} | struct + def browser_type(%Browser{name: name, session: session}) do + playwright = Channel.find(session, {:guid, "Playwright"}) + client_guid = get_in(playwright, [Access.key(String.to_atom(name)), Access.key(:guid)]) + Channel.find(session, {:guid, client_guid}) + end + @doc """ Closes the browser. diff --git a/lib/playwright/browser_type.ex b/lib/playwright/browser_type.ex index 8f0c39d4..b0c2926e 100644 --- a/lib/playwright/browser_type.ex +++ b/lib/playwright/browser_type.ex @@ -77,10 +77,47 @@ defmodule Playwright.BrowserType do end end - # --- + @doc """ + Attaches Playwright to an existing browser instance using the Chrome DevTools Protocol. + + ## Returns + + - `{session, %Playwright.Browser{}}` + + ## Arguments + + ... (many) + + ## Example + + {_, browser} = Playwright.BrowserType.connect_over_cdp(:chromium, "http://127.0.0.1:9222") + + """ + @spec connect_over_cdp(client(), url(), options()) :: Playwright.Browser.t() + def connect_over_cdp(client, endpoint_url \\ nil, options \\ %{}) + + def connect_over_cdp(client, endpoint_url, options) + when is_atom(client) + when client in [:chromium] do + with {:ok, session} <- new_session(Transport.Driver, options), + browser_type <- chromium(session), + browser <- _connect_over_cdp(browser_type, Map.merge(%{"endpointURL" => endpoint_url}, options)) do + {session, browser} + end + end + + def connect_over_cdp(client, _endpoint_url, _options) + when is_atom(client) + when client in [:firefox, :webkit] do + raise RuntimeError, message: "not yet implemented" + end + + defp _connect_over_cdp(%BrowserType{session: session, guid: guid}, params) do + %{browser: browser, default_context: browser_context} = Channel.post(session, {:guid, guid}, "connectOverCDP", params) + if browser_context, do: Channel.patch(browser_context.session, {:guid, browser_context.guid}, %{browser: browser}) + browser + end - # @spec connect_over_cdp(BrowserType.t(), url(), options()) :: Playwright.Browser.t() - # def connect_over_cdp(browser_type, endpoint_url, options \\ %{}) # @spec executable_path(BrowserType.t()) :: String.t() # def executable_path(browser_type) @@ -134,8 +171,11 @@ defmodule Playwright.BrowserType do def launch(client, options) when is_atom(client) when client in [:chromium] do - {:ok, session} = new_session(Transport.Driver, options) - {session, chromium(session)} + with {:ok, session} <- new_session(Transport.Driver, options), + browser_type <- chromium(session), + browser <- browser(browser_type) do + {session, browser} + end end def launch(client, _options) @@ -169,14 +209,9 @@ defmodule Playwright.BrowserType do end defp chromium(session) do - case Channel.find(session, {:guid, "Playwright"}) do - %Playwright{} = playwright -> - %{guid: guid} = playwright.chromium - Channel.find(session, {:guid, guid}) |> browser() - - other -> - raise("expected chromium to return a `Playwright`, received: #{inspect(other)}") - end + playwright = playwright(session) + %{guid: guid} = playwright.chromium + Channel.find(session, {:guid, guid}) end defp new_session(transport, args) do @@ -187,7 +222,15 @@ defmodule Playwright.BrowserType do end defp launched_browser(session) do - playwright = Channel.find(session, {:guid, "Playwright"}) + playwright = playwright(session) playwright.initializer.preLaunchedBrowser end + + defp playwright(session) do + case Channel.find(session, {:guid, "Playwright"}) do + %Playwright{} = playwright -> playwright + other -> + raise("expected to return a `Playwright`, received: #{inspect(other)}") + end + end end diff --git a/lib/playwright/channel/response.ex b/lib/playwright/channel/response.ex index 168c266b..420f8992 100644 --- a/lib/playwright/channel/response.ex +++ b/lib/playwright/channel/response.ex @@ -74,6 +74,13 @@ defmodule Playwright.Channel.Response do result end + defp parse([browser: %{guid: browser_guid}, defaultContext: %{guid: context_guid}], catalog) do + %{ + browser: Catalog.get(catalog, browser_guid), + default_context: Catalog.get(catalog, context_guid) + } + end + defp parse([{:binary, value}], _catalog) do value end From 75df198584f87d65d46f9e1be30936f84b7c1ef9 Mon Sep 17 00:00:00 2001 From: Tim Goodwin Date: Fri, 6 Jan 2023 14:46:51 +0000 Subject: [PATCH 2/2] tests for BrowserType.connect_over_cdp/3 --- lib/playwright/browser_type.ex | 17 ++-- lib/playwright_test/case.ex | 20 +++-- mix.exs | 1 + mix.lock | 9 +++ .../browser_type/connect_cdp_test.exs | 77 ++++++++++++++++++- 5 files changed, 101 insertions(+), 23 deletions(-) diff --git a/lib/playwright/browser_type.ex b/lib/playwright/browser_type.ex index b0c2926e..394c8cd6 100644 --- a/lib/playwright/browser_type.ex +++ b/lib/playwright/browser_type.ex @@ -100,8 +100,8 @@ defmodule Playwright.BrowserType do when is_atom(client) when client in [:chromium] do with {:ok, session} <- new_session(Transport.Driver, options), - browser_type <- chromium(session), - browser <- _connect_over_cdp(browser_type, Map.merge(%{"endpointURL" => endpoint_url}, options)) do + browser_type <- chromium(session), + browser <- _connect_over_cdp(browser_type, Map.merge(%{"endpointURL" => endpoint_url}, options)) do {session, browser} end end @@ -118,7 +118,6 @@ defmodule Playwright.BrowserType do browser end - # @spec executable_path(BrowserType.t()) :: String.t() # def executable_path(browser_type) @@ -162,7 +161,7 @@ defmodule Playwright.BrowserType do > describes some differences for Linux users. """ @spec launch(client() | nil, any()) :: {pid(), Playwright.Browser.t()} - def launch(client \\ nil, options \\ %{}) + def launch(client \\ nil, options \\ Config.launch_options(true)) def launch(nil, options) do launch(:chromium, options) @@ -173,7 +172,7 @@ defmodule Playwright.BrowserType do when client in [:chromium] do with {:ok, session} <- new_session(Transport.Driver, options), browser_type <- chromium(session), - browser <- browser(browser_type) do + browser <- browser(browser_type, options) do {session, browser} end end @@ -204,8 +203,8 @@ defmodule Playwright.BrowserType do # private # ---------------------------------------------------------------------------- - defp browser(%BrowserType{} = browser_type) do - Channel.post(browser_type.session, {:guid, browser_type.guid}, :launch, Config.launch_options(true)) + defp browser(%BrowserType{} = browser_type, launch_options) do + Channel.post(browser_type.session, {:guid, browser_type.guid}, :launch, launch_options) end defp chromium(session) do @@ -228,7 +227,9 @@ defmodule Playwright.BrowserType do defp playwright(session) do case Channel.find(session, {:guid, "Playwright"}) do - %Playwright{} = playwright -> playwright + %Playwright{} = playwright -> + playwright + other -> raise("expected to return a `Playwright`, received: #{inspect(other)}") end diff --git a/lib/playwright_test/case.ex b/lib/playwright_test/case.ex index 364990c8..cab8993b 100644 --- a/lib/playwright_test/case.ex +++ b/lib/playwright_test/case.ex @@ -52,10 +52,9 @@ defmodule PlaywrightTest.Case do launch_options = Map.merge(Config.launch_options(), inline_options) runner_options = Map.merge(Config.playwright_test(), inline_options) - Application.put_env(:playwright, LaunchOptions, launch_options) {:ok, _} = Application.ensure_all_started(:playwright) - {_session, browser} = setup_browser(runner_options.transport) + {_session, browser} = setup_browser(runner_options.transport, runner_options) [browser: browser, transport: runner_options.transport] end @@ -78,17 +77,16 @@ defmodule PlaywrightTest.Case do end # --- + defp setup_browser(transport, transport_options \\ %{}) - defp setup_browser(transport) do - case transport do - :driver -> - options = Config.launch_options() - Playwright.BrowserType.launch(options) + defp setup_browser(:driver, transport_options) do + options = Map.merge(Config.launch_options(), transport_options) + Playwright.BrowserType.launch(options) + end - :websocket -> - options = Config.connect_options() - Playwright.BrowserType.connect(options.ws_endpoint) - end + defp setup_browser(:websocket, transport_options) do + options = Map.merge(Config.connect_options(), transport_options) + Playwright.BrowserType.connect(options.ws_endpoint) end end end diff --git a/mix.exs b/mix.exs index 2ef8436e..f24da83c 100644 --- a/mix.exs +++ b/mix.exs @@ -52,6 +52,7 @@ defmodule Playwright.MixProject do {:ex_doc, "~> 0.25", only: :dev, runtime: false}, {:esbuild, "~> 0.4", runtime: Mix.env() == :dev}, {:gun, "~> 1.3.3"}, + {:httpoison, "~> 1.8", only: [:test]}, {:jason, "~> 1.2"}, {:mix_audit, "~> 1.0", only: [:dev, :test], runtime: false}, {:playwright_assets, "~> 1.18.1", only: [:test]}, diff --git a/mix.lock b/mix.lock index 8b61923a..0aafc3d9 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,7 @@ %{ "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, "castore": {:hex, :castore, "0.1.13", "ccf3ab251ffaebc4319f41d788ce59a6ab3f42b6c27e598ad838ffecee0b04f9", [:mix], [], "hexpm", "a14a7eecfec7e20385493dbb92b0d12c5d77ecfd6307de10102d58c94e8c49c0"}, + "certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"}, "cowboy": {:hex, :cowboy, "2.6.3", "99aa50e94e685557cad82e704457336a453d4abcb77839ad22dbe71f311fcc06", [:rebar3], [{:cowlib, "~> 2.7.3", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "e5580029080f3f1ad17436fb97b0d5ed2ed4e4815a96bac36b5a992e20f58db6"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowlib": {:hex, :cowlib, "2.7.3", "a7ffcd0917e6d50b4d5fb28e9e2085a0ceb3c97dea310505f7460ff5ed764ce9", [:rebar3], [], "hexpm", "1e1a3d176d52daebbecbbcdfd27c27726076567905c2a9d7398c54da9d225761"}, @@ -12,21 +13,29 @@ "ex_doc": {:hex, :ex_doc, "0.25.5", "ac3c5425a80b4b7c4dfecdf51fa9c23a44877124dd8ca34ee45ff608b1c6deb9", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "688cfa538cdc146bc4291607764a7f1fcfa4cce8009ecd62de03b27197528350"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "gun": {:hex, :gun, "1.3.3", "cf8b51beb36c22b9c8df1921e3f2bc4d2b1f68b49ad4fbc64e91875aa14e16b4", [:rebar3], [{:cowlib, "~> 2.7.0", [hex: :cowlib, repo: "hexpm", optional: false]}], "hexpm", "3106ce167f9c9723f849e4fb54ea4a4d814e3996ae243a1c828b256e749041e0"}, + "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"}, + "httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"}, + "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, "json_diff": {:hex, :json_diff, "0.1.3", "c80d5ca5416e785867e765e906e9a91b7efc35bfd505af276654d108f4995736", [:mix], [], "hexpm", "a5332e8293e7e9f384d34ea44645d7961334db73739165178fd4a7728d06f7d1"}, "makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"}, "makeup_elixir": {:hex, :makeup_elixir, "0.15.2", "dc72dfe17eb240552857465cc00cce390960d9a0c055c4ccd38b70629227e97c", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "fd23ae48d09b32eff49d4ced2b43c9f086d402ee4fd4fcb2d7fad97fa8823e75"}, "makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.2", "0b9e1a4c840eafb68d820b0e2158ef5c49385d17fb36855ac6e7e087d4b1dcc5", [:mix], [], "hexpm", "e6a3f76b4c277739e36c2e21a2c640778ba4c3846189d5ab19f97f126df5f9b7"}, + "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "mix_audit": {:hex, :mix_audit, "1.0.0", "d2b5adbd69f34ba6b5b7d52812b1ba06f9110367e196d3ba5dba7753124cf8be", [:make, :mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.8.0", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "1b1ff6694e6eb12818ce5dcc276a39bbe03e27fcd11376c381bfe6b4900f2aa8"}, "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, + "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, "playwright_assets": {:hex, :playwright_assets, "1.18.1", "3398a85f0281f05cbe12c89709ff60f831f262356f6275e536ab8d2e0f4fb6ec", [:mix], [{:cowlib, "~> 2.7.3", [hex: :cowlib, repo: "hexpm", optional: false]}, {:plug, "~> 1.12", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.1.3", [hex: :plug_cowboy, repo: "hexpm", optional: false]}], "hexpm", "78e6940c3bac4f21f206597b9c264db005a6dc54b3135976ef2723042147e54e"}, "plug": {:hex, :plug, "1.13.2", "33aba8e2b43ddd68d9d49b818ed2fb46da85f4ec3229bc4bcd0c981a640a4e71", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a95cdfe599e3524b98684376c3f3494cbfbc1f41fcddefc380cac3138dd7619d"}, "plug_cowboy": {:hex, :plug_cowboy, "2.1.3", "38999a3e85e39f0e6bdfdf820761abac61edde1632cfebbacc445cdcb6ae1333", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "056f41f814dbb38ea44613e0f613b3b2b2f2c6afce64126e252837669eba84db"}, "plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"}, "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"}, "recase": {:hex, :recase, "0.7.0", "3f2f719f0886c7a3b7fe469058ec539cb7bbe0023604ae3bce920e186305e5ae", [:mix], [], "hexpm", "36f5756a9f552f4a94b54a695870e32f4e72d5fad9c25e61bc4a3151c08a4e0c"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, "telemetry": {:hex, :telemetry, "1.0.0", "0f453a102cdf13d506b7c0ab158324c337c41f1cc7548f0bc0e130bbf0ae9452", [:rebar3], [], "hexpm", "73bc09fa59b4a0284efb4624335583c528e07ec9ae76aca96ea0673850aec57a"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, "uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [:mix], [], "hexpm", "c790593b4c3b601f5dc2378baae7efaf5b3d73c4c6456ba85759905be792f2ac"}, "yamerl": {:hex, :yamerl, "0.8.1", "07da13ffa1d8e13948943789665c62ccd679dfa7b324a4a2ed3149df17f453a4", [:rebar3], [], "hexpm", "96cb30f9d64344fed0ef8a92e9f16f207de6c04dfff4f366752ca79f5bceb23f"}, "yaml_elixir": {:hex, :yaml_elixir, "2.8.0", "c7ff0034daf57279c2ce902788ce6fdb2445532eb4317e8df4b044209fae6832", [:mix], [{:yamerl, "~> 0.8", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "4b674bd881e373d1ac6a790c64b2ecb69d1fd612c2af3b22de1619c15473830b"}, diff --git a/test/integration/browser_type/connect_cdp_test.exs b/test/integration/browser_type/connect_cdp_test.exs index 7b57628f..7421eea8 100644 --- a/test/integration/browser_type/connect_cdp_test.exs +++ b/test/integration/browser_type/connect_cdp_test.exs @@ -1,7 +1,76 @@ defmodule Playwright.BrowserType.ConnectCDPTest do - use Playwright.TestCase, async: true + @remote_debug_port "9223" - # test_connect_to_an_existing_cdp_session - # test_connect_to_an_existing_cdp_session_twice - # test_conect_over_a_ws_endpoint + use Playwright.TestCase, async: true, args: ["--remote-debugging-port=#{@remote_debug_port}"] + + alias Playwright.{Browser, BrowserType, BrowserContext, Page} + + describe "BrowserType.connect_over_cdp/3" do + test "can connect to an existing cdp session", %{browser: browser} do + {_, cdp_browser} = BrowserType.connect_over_cdp(:chromium, "http://localhost:#{@remote_debug_port}") + + assert_browser_context_count(cdp_browser, 1) + assert_page_count(cdp_browser, 1) + assert browser.session != cdp_browser.session + end + + @tag exclude: [:page] + test "can connect to an existing CDP Session twice", %{browser: _browser, assets: assets} do + {_, cdp_browser1} = BrowserType.connect_over_cdp(:chromium, "http://localhost:#{@remote_debug_port}") + {_, cdp_browser2} = BrowserType.connect_over_cdp(:chromium, "http://localhost:#{@remote_debug_port}") + + assert_browser_context_count(cdp_browser1, 1) + assert_browser_context_count(cdp_browser2, 1) + + assert_page_count(cdp_browser1, 0) + assert_page_count(cdp_browser2, 0) + + page1 = create_new_page(cdp_browser1, assets.empty) + assert_page_count(cdp_browser1, 1) + assert_page_count(cdp_browser2, 1) + + page2 = create_new_page(cdp_browser2, assets.empty) + assert_page_count(cdp_browser1, 2) + assert_page_count(cdp_browser2, 2) + + close_page(page1) + close_page(page2) + end + + test "can connect over a websocket endpoint", %{browser: _browser} do + ws_endpoint = ws_endpoint_for_url("http://localhost:#{@remote_debug_port}/json/version") + {_, cdp_browser1} = BrowserType.connect_over_cdp(:chromium, ws_endpoint) + + assert_browser_context_count(cdp_browser1, 1) + + {_, cdp_browser2} = BrowserType.connect_over_cdp(:chromium, ws_endpoint) + assert_browser_context_count(cdp_browser2, 1) + end + + defp ws_endpoint_for_url(url) do + url + |> HTTPoison.get!() + |> Map.get(:body) + |> Jason.decode!() + |> Map.get("webSocketDebuggerUrl") + end + + defp create_new_page(%Browser{} = browser, url) do + page = browser |> Browser.contexts() |> Enum.at(0) |> BrowserContext.new_page() + page |> Page.goto(url) + page + end + + defp close_page(%Page{} = page) do + page |> Page.close() + end + + defp assert_browser_context_count(%Browser{} = browser, expected_count) do + assert browser |> Browser.contexts() |> length() == expected_count + end + + defp assert_page_count(%Browser{} = browser, expected_count) do + assert browser |> Browser.contexts() |> Enum.at(0) |> BrowserContext.pages() |> length() == expected_count + end + end end