From 38d498571537f43e5a94eb5b2247089475892c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20de=20Alc=C3=A2ntara=20Barroso?= Date: Thu, 14 Jul 2022 11:56:23 +0100 Subject: [PATCH 1/6] Add visible_html to assertions --- lib/phoenix_integration/assertions.ex | 57 +++++++++++++++++++++++++++ test/assertions_test.exs | 56 ++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/lib/phoenix_integration/assertions.ex b/lib/phoenix_integration/assertions.ex index 1ab1fed..1777519 100644 --- a/lib/phoenix_integration/assertions.ex +++ b/lib/phoenix_integration/assertions.ex @@ -84,6 +84,7 @@ defmodule PhoenixIntegration.Assertions do :content_type -> assert_content_type(conn, value) :body -> assert_body(conn, value) :html -> assert_body_html(conn, value) + :visible_html -> assert_visible_html(conn, value) :json -> assert_body_json(conn, value) :uri -> assert_uri(conn, value) :path -> assert_uri(conn, value, :path) @@ -140,6 +141,7 @@ defmodule PhoenixIntegration.Assertions do :content_type -> refute_content_type(conn, value) :body -> refute_body(conn, value) :html -> refute_body_html(conn, value) + :visible_html -> refute_visible_html(conn, value) :json -> refute_body_json(conn, value) :uri -> refute_uri(conn, value) :path -> refute_uri(conn, value, :path) @@ -381,6 +383,30 @@ defmodule PhoenixIntegration.Assertions do end end + # ---------------------------------------------------------------------------- + defp assert_visible_html(conn, expected, err_type \\ :html) do + assert_content_type(conn, "text/html", err_type) + |> assert_visible_html_body(expected, err_type) + end + + # ---------------------------------------------------------------------------- + defp refute_visible_html(conn, expected, err_type \\ :html) do + # similar to refute body html, ok if content isn't html + case Plug.Conn.get_resp_header(conn, "content-type") do + [] -> + conn + + [header] -> + cond do + header =~ "text/html" -> + refute_visible_html_body(conn, expected, err_type) + + true -> + conn + end + end + end + # ---------------------------------------------------------------------------- defp assert_body_json(conn, expected, err_type \\ :json) do assert_content_type(conn, "application/json", err_type) @@ -455,6 +481,37 @@ defmodule PhoenixIntegration.Assertions do end end + # ---------------------------------------------------------------------------- + defp assert_visible_html_body(conn, expected, err_type) do + visible_text = Floki.text(conn.resp_body) + if visible_text =~ expected do + conn + else + msg = + error_msg_type(conn, err_type) <> + error_msg_expected("to find \"#{inspect(expected)}\"") <> + error_msg_found("Not visible in the response body\n") <> IO.ANSI.yellow() <> visible_text + + raise %ResponseError{message: msg} + end + end + + # ---------------------------------------------------------------------------- + defp refute_visible_html_body(conn, expected, err_type) do + visible_text = Floki.text(conn.resp_body) + if visible_text =~ expected do + msg = + error_msg_type(conn, err_type) <> + error_msg_expected("NOT to find \"#{inspect(expected)}\"") <> + error_msg_found("in the visible response body\n") <> IO.ANSI.yellow() <> visible_text + + raise %ResponseError{message: msg} + else + conn + end + end + + # ---------------------------------------------------------------------------- defp assert_status(conn, status, err_type \\ :status) do case conn.status do diff --git a/test/assertions_test.exs b/test/assertions_test.exs index 87f498e..aaf7f94 100644 --- a/test/assertions_test.exs +++ b/test/assertions_test.exs @@ -246,6 +246,42 @@ defmodule PhoenixIntegration.AssertionsTest do end end + # ---------------------------------------------------------------------------- + # assert visible html + test "assert_response :visible_html succeeds", %{conn: conn} do + conn = get(conn, "/sample") + + PhoenixIntegration.Assertions.assert_response( + conn, + body: "Sample", + body: "Page" + ) + end + + test "assert_response :visible_html fails if wrong type", %{conn: conn} do + conn = get(conn, "/test_json") + + assert_raise PhoenixIntegration.Assertions.ResponseError, fn -> + PhoenixIntegration.Assertions.assert_response(conn, visible_html: "Sample Page") + end + end + + test "assert_response :visible_html fails if missing content", %{conn: conn} do + conn = get(conn, "/sample") + + assert_raise PhoenixIntegration.Assertions.ResponseError, fn -> + PhoenixIntegration.Assertions.assert_response(conn, visible_html: "href=\"/links/first\"") + end + end + + test "assert_response :visible_html fails if missing content for regexp", %{conn: conn} do + conn = get(conn, "/sample") + + assert_raise PhoenixIntegration.Assertions.ResponseError, fn -> + PhoenixIntegration.Assertions.assert_response(conn, visible_html: ~r/invalid content/) + end + end + # ---------------------------------------------------------------------------- # assert json test "assert_response :json succeeds", %{conn: conn} do @@ -400,6 +436,26 @@ defmodule PhoenixIntegration.AssertionsTest do end end + # ---------------------------------------------------------------------------- + # refute visible_html + test "refute_response :visible_html succeeds with wrong content", %{conn: conn} do + conn = get(conn, "/sample") + PhoenixIntegration.Assertions.refute_response(conn, body: "not_in_body") + end + + test "refute_response :visible_html succeeds if wrong type", %{conn: conn} do + conn = get(conn, "/test_json") + PhoenixIntegration.Assertions.refute_response(conn, visible_html: "Sample") + end + + test "refute_response :visible_html fails if contains content", %{conn: conn} do + conn = get(conn, "/sample") + + assert_raise PhoenixIntegration.Assertions.ResponseError, fn -> + PhoenixIntegration.Assertions.refute_response(conn, visible_html: "Sample Page") + end + end + # ---------------------------------------------------------------------------- # refute json test "refute_response :json succeeds", %{conn: conn} do From 735c69e273d6ca90f0d9be03d70067bb6416c4ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20de=20Alc=C3=A2ntara=20Barroso?= Date: Thu, 28 Jul 2022 23:12:55 +0100 Subject: [PATCH 2/6] Add options to Floki.text --- lib/phoenix_integration/assertions.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/phoenix_integration/assertions.ex b/lib/phoenix_integration/assertions.ex index 1777519..979e068 100644 --- a/lib/phoenix_integration/assertions.ex +++ b/lib/phoenix_integration/assertions.ex @@ -483,7 +483,7 @@ defmodule PhoenixIntegration.Assertions do # ---------------------------------------------------------------------------- defp assert_visible_html_body(conn, expected, err_type) do - visible_text = Floki.text(conn.resp_body) + visible_text = Floki.text(conn.resp_body, style: false, sep: " ") if visible_text =~ expected do conn else From 4e524f06fb8328123499b6051e56303a39008556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20de=20Alc=C3=A2ntara=20Barroso?= Date: Thu, 28 Jul 2022 23:20:03 +0100 Subject: [PATCH 3/6] s/visible_html/text --- lib/phoenix_integration/assertions.ex | 20 ++++++++++--------- test/assertions_test.exs | 28 +++++++++++++-------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/lib/phoenix_integration/assertions.ex b/lib/phoenix_integration/assertions.ex index 979e068..6a64edf 100644 --- a/lib/phoenix_integration/assertions.ex +++ b/lib/phoenix_integration/assertions.ex @@ -45,6 +45,7 @@ defmodule PhoenixIntegration.Assertions do values are `"text/html"` or `"application/json"` * `:body` conn.resp_body should contain the given text. Does not check the content_type. * `:html` checks that content_type is html, then looks for the given text in the body. + * `:text` checks that content_type is html, then looks for the given text in the visible text of the document. * `:json` checks that content_type is json, then checks that the json data equals the given map. * `:path` the route rendered into the conn must equal the given path (or uri). * `:uri` same as `:path` @@ -84,7 +85,7 @@ defmodule PhoenixIntegration.Assertions do :content_type -> assert_content_type(conn, value) :body -> assert_body(conn, value) :html -> assert_body_html(conn, value) - :visible_html -> assert_visible_html(conn, value) + :text -> assert_text(conn, value) :json -> assert_body_json(conn, value) :uri -> assert_uri(conn, value) :path -> assert_uri(conn, value, :path) @@ -111,6 +112,7 @@ defmodule PhoenixIntegration.Assertions do values are `"text/html"` or `"applicaiton/json"` * `:body` conn.resp_body should not contain the given text. Does not check the content_type. * `:html` checks if content_type is html. If it is, it then checks that the given text is not in the body. + * `:text` checks if content_type is html. If it is, it then checks that the given text is not in the document text. * `:json` checks if content_type is json, then checks that the json data does not equal the given map. * `:path` the route rendered into the conn must not equal the given path (or uri). * `:uri` same as `:path` @@ -141,7 +143,7 @@ defmodule PhoenixIntegration.Assertions do :content_type -> refute_content_type(conn, value) :body -> refute_body(conn, value) :html -> refute_body_html(conn, value) - :visible_html -> refute_visible_html(conn, value) + :text -> refute_text(conn, value) :json -> refute_body_json(conn, value) :uri -> refute_uri(conn, value) :path -> refute_uri(conn, value, :path) @@ -384,13 +386,13 @@ defmodule PhoenixIntegration.Assertions do end # ---------------------------------------------------------------------------- - defp assert_visible_html(conn, expected, err_type \\ :html) do + defp assert_text(conn, expected, err_type \\ :html) do assert_content_type(conn, "text/html", err_type) - |> assert_visible_html_body(expected, err_type) + |> assert_visible_html_text(expected, err_type) end # ---------------------------------------------------------------------------- - defp refute_visible_html(conn, expected, err_type \\ :html) do + defp refute_text(conn, expected, err_type \\ :html) do # similar to refute body html, ok if content isn't html case Plug.Conn.get_resp_header(conn, "content-type") do [] -> @@ -399,7 +401,7 @@ defmodule PhoenixIntegration.Assertions do [header] -> cond do header =~ "text/html" -> - refute_visible_html_body(conn, expected, err_type) + refute_visible_html_text(conn, expected, err_type) true -> conn @@ -482,7 +484,7 @@ defmodule PhoenixIntegration.Assertions do end # ---------------------------------------------------------------------------- - defp assert_visible_html_body(conn, expected, err_type) do + defp assert_visible_html_text(conn, expected, err_type) do visible_text = Floki.text(conn.resp_body, style: false, sep: " ") if visible_text =~ expected do conn @@ -497,8 +499,8 @@ defmodule PhoenixIntegration.Assertions do end # ---------------------------------------------------------------------------- - defp refute_visible_html_body(conn, expected, err_type) do - visible_text = Floki.text(conn.resp_body) + defp refute_visible_html_text(conn, expected, err_type) do + visible_text = Floki.text(conn.resp_body, style: false, sep: " ") if visible_text =~ expected do msg = error_msg_type(conn, err_type) <> diff --git a/test/assertions_test.exs b/test/assertions_test.exs index aaf7f94..628724f 100644 --- a/test/assertions_test.exs +++ b/test/assertions_test.exs @@ -247,8 +247,8 @@ defmodule PhoenixIntegration.AssertionsTest do end # ---------------------------------------------------------------------------- - # assert visible html - test "assert_response :visible_html succeeds", %{conn: conn} do + # assert text + test "assert_response :text succeeds", %{conn: conn} do conn = get(conn, "/sample") PhoenixIntegration.Assertions.assert_response( @@ -258,27 +258,27 @@ defmodule PhoenixIntegration.AssertionsTest do ) end - test "assert_response :visible_html fails if wrong type", %{conn: conn} do + test "assert_response :text fails if wrong type", %{conn: conn} do conn = get(conn, "/test_json") assert_raise PhoenixIntegration.Assertions.ResponseError, fn -> - PhoenixIntegration.Assertions.assert_response(conn, visible_html: "Sample Page") + PhoenixIntegration.Assertions.assert_response(conn, text: "Sample Page") end end - test "assert_response :visible_html fails if missing content", %{conn: conn} do + test "assert_response :text fails if missing content", %{conn: conn} do conn = get(conn, "/sample") assert_raise PhoenixIntegration.Assertions.ResponseError, fn -> - PhoenixIntegration.Assertions.assert_response(conn, visible_html: "href=\"/links/first\"") + PhoenixIntegration.Assertions.assert_response(conn, text: "href=\"/links/first\"") end end - test "assert_response :visible_html fails if missing content for regexp", %{conn: conn} do + test "assert_response :text fails if missing content for regexp", %{conn: conn} do conn = get(conn, "/sample") assert_raise PhoenixIntegration.Assertions.ResponseError, fn -> - PhoenixIntegration.Assertions.assert_response(conn, visible_html: ~r/invalid content/) + PhoenixIntegration.Assertions.assert_response(conn, text: ~r/invalid content/) end end @@ -437,22 +437,22 @@ defmodule PhoenixIntegration.AssertionsTest do end # ---------------------------------------------------------------------------- - # refute visible_html - test "refute_response :visible_html succeeds with wrong content", %{conn: conn} do + # refute text + test "refute_response :text succeeds with wrong content", %{conn: conn} do conn = get(conn, "/sample") PhoenixIntegration.Assertions.refute_response(conn, body: "not_in_body") end - test "refute_response :visible_html succeeds if wrong type", %{conn: conn} do + test "refute_response :text succeeds if wrong type", %{conn: conn} do conn = get(conn, "/test_json") - PhoenixIntegration.Assertions.refute_response(conn, visible_html: "Sample") + PhoenixIntegration.Assertions.refute_response(conn, text: "Sample") end - test "refute_response :visible_html fails if contains content", %{conn: conn} do + test "refute_response :text fails if contains content", %{conn: conn} do conn = get(conn, "/sample") assert_raise PhoenixIntegration.Assertions.ResponseError, fn -> - PhoenixIntegration.Assertions.refute_response(conn, visible_html: "Sample Page") + PhoenixIntegration.Assertions.refute_response(conn, text: "Sample Page") end end From 8b929b5c1e8eba71bd14888f40bb2740fe361a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20de=20Alc=C3=A2ntara=20Barroso?= Date: Thu, 28 Jul 2022 23:26:23 +0100 Subject: [PATCH 4/6] Fix deprecation warning --- lib/phoenix_integration/assertions.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/phoenix_integration/assertions.ex b/lib/phoenix_integration/assertions.ex index 6a64edf..5731f40 100644 --- a/lib/phoenix_integration/assertions.ex +++ b/lib/phoenix_integration/assertions.ex @@ -485,7 +485,7 @@ defmodule PhoenixIntegration.Assertions do # ---------------------------------------------------------------------------- defp assert_visible_html_text(conn, expected, err_type) do - visible_text = Floki.text(conn.resp_body, style: false, sep: " ") + visible_text = conn.resp_body |> Floki.parse_document!() |> Floki.text(style: false, sep: " ") if visible_text =~ expected do conn else @@ -500,7 +500,7 @@ defmodule PhoenixIntegration.Assertions do # ---------------------------------------------------------------------------- defp refute_visible_html_text(conn, expected, err_type) do - visible_text = Floki.text(conn.resp_body, style: false, sep: " ") + visible_text = conn.resp_body |> Floki.parse_document!() |> Floki.text(style: false, sep: " ") if visible_text =~ expected do msg = error_msg_type(conn, err_type) <> From 1e4401bc0c3cb3eb35a2fcd7b1987db2691cc7a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20de=20Alc=C3=A2ntara=20Barroso?= Date: Thu, 28 Jul 2022 23:27:52 +0100 Subject: [PATCH 5/6] Tweak error message --- lib/phoenix_integration/assertions.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/phoenix_integration/assertions.ex b/lib/phoenix_integration/assertions.ex index 5731f40..6c7cbc9 100644 --- a/lib/phoenix_integration/assertions.ex +++ b/lib/phoenix_integration/assertions.ex @@ -492,7 +492,7 @@ defmodule PhoenixIntegration.Assertions do msg = error_msg_type(conn, err_type) <> error_msg_expected("to find \"#{inspect(expected)}\"") <> - error_msg_found("Not visible in the response body\n") <> IO.ANSI.yellow() <> visible_text + error_msg_found("Not visible in the html text of the response\n") <> IO.ANSI.yellow() <> visible_text raise %ResponseError{message: msg} end @@ -505,7 +505,7 @@ defmodule PhoenixIntegration.Assertions do msg = error_msg_type(conn, err_type) <> error_msg_expected("NOT to find \"#{inspect(expected)}\"") <> - error_msg_found("in the visible response body\n") <> IO.ANSI.yellow() <> visible_text + error_msg_found("in the html text of the response\n") <> IO.ANSI.yellow() <> visible_text raise %ResponseError{message: msg} else From a41188f4aa2685bcb34da721d8a5345e80129ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20de=20Alc=C3=A2ntara=20Barroso?= Date: Thu, 11 Jan 2024 17:47:36 +0100 Subject: [PATCH 6/6] Drop unused phoenix_html dependency --- mix.exs | 1 - mix.lock | 2 -- 2 files changed, 3 deletions(-) diff --git a/mix.exs b/mix.exs index 94a8087..0c1e008 100644 --- a/mix.exs +++ b/mix.exs @@ -43,7 +43,6 @@ defmodule PhoenixIntegration.Mixfile do defp deps do [ {:phoenix, "~> 1.3"}, - {:phoenix_html, "~> 2.10 or ~> 3.0"}, {:floki, ">= 0.24.0"}, {:jason, "~> 1.1"}, {:flow_assertions, "~> 0.7", only: :test}, diff --git a/mix.lock b/mix.lock index 90ddfb9..26b6ef9 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,5 @@ %{ "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, - "earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"}, "earmark_parser": {:hex, :earmark_parser, "1.4.15", "b29e8e729f4aa4a00436580dcc2c9c5c51890613457c193cc8525c388ccb2f06", [:mix], [], "hexpm", "044523d6438ea19c1b8ec877ec221b008661d3c27e3b848f4c879f500421ca5c"}, "ex_doc": {:hex, :ex_doc, "0.25.3", "3edf6a0d70a39d2eafde030b8895501b1c93692effcbd21347296c18e47618ce", [: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", "9ebebc2169ec732a38e9e779fd0418c9189b3ca93f4a676c961be6c1527913f5"}, "floki": {:hex, :floki, "0.31.0", "f05ee8a8e6a3ced4e62beeb2c79a63bc8e12ab98fbaaf6e6a3d9b76b1278e23f", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "b05afa372f5c345a5bf240ac25ea1f0f3d5fcfd7490ac0beeb4a203f9444891e"}, @@ -14,7 +13,6 @@ "mime": {:hex, :mime, "2.0.1", "0de4c81303fe07806ebc2494d5321ce8fb4df106e34dd5f9d787b637ebadc256", [:mix], [], "hexpm", "7a86b920d2aedce5fb6280ac8261ac1a739ae6c1a1ad38f5eadf910063008942"}, "nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"}, "phoenix": {:hex, :phoenix, "1.6.0", "7b85023f7ddef9a5c70909a51cc37c8b868b474d853f90f4280efd26b0e7cce5", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "52ffdd31f2daeb399b2e1eb57d468f99a1ad6eee5d8ea19d2353492f06c9fc96"}, - "phoenix_html": {:hex, :phoenix_html, "3.0.4", "232d41884fe6a9c42d09f48397c175cd6f0d443aaa34c7424da47604201df2e1", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "ce17fd3cf815b2ed874114073e743507704b1f5288bb03c304a77458485efc8b"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"}, "phoenix_view": {:hex, :phoenix_view, "1.0.0", "fea71ecaaed71178b26dd65c401607de5ec22e2e9ef141389c721b3f3d4d8011", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "82be3e2516f5633220246e2e58181282c71640dab7afc04f70ad94253025db0c"}, "plug": {:hex, :plug, "1.12.1", "645678c800601d8d9f27ad1aebba1fdb9ce5b2623ddb961a074da0b96c35187d", [: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", "d57e799a777bc20494b784966dc5fbda91eb4a09f571f76545b72a634ce0d30b"},