From f346cde9650e0e5f4bb7fbecb69467e1e9b5f784 Mon Sep 17 00:00:00 2001 From: Alexandre Moreira Xavier Date: Wed, 15 Mar 2023 13:41:56 -0300 Subject: [PATCH 1/2] Add an additional validate_heex func that doesn't throw exceptions when invalid template --- lib/safe_code/validator.ex | 12 ++++++++++ test/safe_code/validator_test.exs | 40 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/lib/safe_code/validator.ex b/lib/safe_code/validator.ex index 80aef8a..c3dfae0 100644 --- a/lib/safe_code/validator.ex +++ b/lib/safe_code/validator.ex @@ -25,6 +25,18 @@ defmodule SafeCode.Validator do |> validate_quoted(opts) end + @spec validate_heex(binary, keyword) :: {:ok, ast :: Macro.t()} | {:error, %Phoenix.LiveView.HTMLTokenizer.ParseError{}} + def validate_heex(heex, opts \\ []) when is_binary(heex) do + quoted = + heex + |> HeexParser.parse_template() + |> validate_quoted(include_phoenix(opts)) + + {:ok, quoted} + rescue + error in Phoenix.LiveView.HTMLTokenizer.ParseError -> {:error, error} + end + def validate_heex!(heex, opts \\ []) when is_binary(heex) do heex |> HeexParser.parse_template() diff --git a/test/safe_code/validator_test.exs b/test/safe_code/validator_test.exs index dea53da..e139bef 100644 --- a/test/safe_code/validator_test.exs +++ b/test/safe_code/validator_test.exs @@ -33,6 +33,46 @@ defmodule SafeCode.ValidatorTest do end describe "validate_heex/1" do + test "basic" do + heex = """ + hello <%= 1 + 1 %> how <%= 2+2 %> are you + """ + + assert {:ok, _quoted} = Validator.validate_heex(heex) + end + + test "for loop" do + heex = """ + <%= for foo <- bar do %> + <%= foo %> + <% end %> + """ + + assert {:ok, _quoted} = Validator.validate_heex(heex) + end + + test "return the error tuple when invalid template" do + heex = """ +
+ hello <%= 1 + 1 %> how <%= 2+2 %> are you + """ + + assert {:error, %Phoenix.LiveView.HTMLTokenizer.ParseError{} = error} = Validator.validate_heex(heex) + assert error.description == "end of template reached without closing tag for
" + end + + test "raises on problem function" do + str = """ + <%= System.cmd("touch", ["foo"]) %> + """ + + assert_raise InvalidNode, "System . :cmd\n\nast:\n{:., [line: 1], [{:__aliases__, [line: 1], [:System]}, :cmd]}", fn -> + Validator.validate_heex(str) + end + end + end + + describe "validate_heex!/1" do test "basic" do heex = """ hello <%= 1 + 1 %> how <%= 2+2 %> are you From c4a2ff033fcc7a19448eeddaa89edcdf37e9b29c Mon Sep 17 00:00:00 2001 From: Alexandre Moreira Xavier Date: Wed, 15 Mar 2023 15:23:21 -0300 Subject: [PATCH 2/2] capture and return whatever exception raises to maintain the return consistent Co-authored-by: Leandro Pereira --- lib/safe_code/validator.ex | 4 ++-- test/safe_code/validator_test.exs | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/safe_code/validator.ex b/lib/safe_code/validator.ex index c3dfae0..080aca1 100644 --- a/lib/safe_code/validator.ex +++ b/lib/safe_code/validator.ex @@ -25,7 +25,7 @@ defmodule SafeCode.Validator do |> validate_quoted(opts) end - @spec validate_heex(binary, keyword) :: {:ok, ast :: Macro.t()} | {:error, %Phoenix.LiveView.HTMLTokenizer.ParseError{}} + @spec validate_heex(binary, keyword) :: {:ok, ast :: Macro.t()} | {:error, Exception.t()} def validate_heex(heex, opts \\ []) when is_binary(heex) do quoted = heex @@ -34,7 +34,7 @@ defmodule SafeCode.Validator do {:ok, quoted} rescue - error in Phoenix.LiveView.HTMLTokenizer.ParseError -> {:error, error} + error -> {:error, error} end def validate_heex!(heex, opts \\ []) when is_binary(heex) do diff --git a/test/safe_code/validator_test.exs b/test/safe_code/validator_test.exs index e139bef..56072cc 100644 --- a/test/safe_code/validator_test.exs +++ b/test/safe_code/validator_test.exs @@ -61,14 +61,13 @@ defmodule SafeCode.ValidatorTest do assert error.description == "end of template reached without closing tag for
" end - test "raises on problem function" do + test "return an error tuple on problem function" do str = """ <%= System.cmd("touch", ["foo"]) %> """ - assert_raise InvalidNode, "System . :cmd\n\nast:\n{:., [line: 1], [{:__aliases__, [line: 1], [:System]}, :cmd]}", fn -> - Validator.validate_heex(str) - end + assert {:error, %InvalidNode{} = error} = Validator.validate_heex(str) + assert error.message == "System . :cmd\n\nast:\n{:., [line: 1], [{:__aliases__, [line: 1], [:System]}, :cmd]}" end end