Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions lib/helper/converter/editor_to_html/index.ex
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
# defmodule Helper.Converter.EditorToHTML.Parser do
# @moduledoc false

# # TODO: map should be editor_block
# @callback parse_block(editor_json :: Map.t()) :: String.t()
# end

defmodule Helper.Converter.EditorToHTML do
@moduledoc """
parse editor.js's json data to raw html and sanitize it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ defmodule Helper.Converter.EditorToHTML.Validator.EditorSchema do

def get("table") do
[
parent: %{"columnCount" => [:number], "items" => [:list]},
parent: %{"columnCount" => [:number, min: 2], "items" => [:list]},
item: %{
"text" => [:string],
"align" => [enum: @valid_table_align],
Expand Down
80 changes: 77 additions & 3 deletions lib/helper/validator/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Helper.Validator.Schema do
currently support boolean / string / number / enum
"""

use Helper.Validator.Schema.Matchers, [:string, :number, :list, :boolean]
# use Helper.Validator.Schema.Matchers, [:string, :number, :list, :boolean]

@doc """
cast data by given schema
Expand Down Expand Up @@ -49,10 +49,9 @@ defmodule Helper.Validator.Schema do
end)
end

# enum
defp match(field, nil, enum: _, required: false), do: done(field, nil)

defp match(field, value, enum: enum, required: false) do
defp match(field, value, enum: enum, required: _) do
match(field, value, enum: enum)
end

Expand All @@ -70,9 +69,84 @@ defmodule Helper.Validator.Schema do
end
end

defp match(field, value, [type | options]) do
match(field, value, type, options)
end

defp match(field, nil, _type, [{:required, false} | _options]) do
done(field, nil)
end

defp match(field, value, type, [{:required, _} | options]) do
match(field, value, type, options)
end

# custom validate logic
defp match(field, value, :string, [{:min, min} | options])
when is_binary(value) and is_integer(min) do
case String.length(value) >= min do
true ->
match(field, value, :string, options)

false ->
error(field, value, :min, min)
end
end

defp match(field, value, :number, [{:min, min} | options])
when is_integer(value) and is_integer(min) do
case value >= min do
true ->
match(field, value, :number, options)

false ->
error(field, value, :min, min)
end
end

# custom validate logic end

# main type
defp match(field, value, :string, []) when is_binary(value), do: done(field, value)
defp match(field, value, :number, []) when is_integer(value), do: done(field, value)
defp match(field, value, :list, []) when is_list(value), do: done(field, value)
defp match(field, value, :boolean, []) when is_boolean(value), do: done(field, value)
# main type end

# judge option
defp match(field, value, type, [option]) when is_tuple(option) do
# 如果这里不判断的话会和下面的 match 冲突,是否有更好的写法?
case option_valid?(option) do
true ->
error(field, value, type)

false ->
{k, v} = option
error(field, value, option: "#{to_string(k)}: #{to_string(v)}")
end
end

defp match(field, value, type, _), do: error(field, value, type)

defp done(field, value), do: {:ok, %{field: field, value: value}}

defp error(field, value, :min, min) do
{:error, %{field: field |> to_string, value: value, message: "min size: #{min}"}}
end

defp error(field, value, option: option) do
{:error, %{field: field |> to_string, value: value, message: "unknow option: #{option}"}}
end

defp error(field, value, :option) do
{:error, %{field: field |> to_string, value: value, message: "unknow option"}}
end

defp error(field, value, schema) do
{:error, %{field: field |> to_string, value: value, message: "should be: #{schema}"}}
end

defp option_valid?({:min, v}) when is_integer(v), do: true
defp option_valid?({:required, v}) when is_boolean(v), do: true
defp option_valid?(_), do: false
end
2 changes: 0 additions & 2 deletions test/helper/converter/editor_to_html_test/header_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ defmodule GroupherServer.Test.Helper.Converter.EditorToHTML.Header do
{:ok, editor_string} = Jason.encode(json)
{:ok, converted} = Parser.to_html(editor_string)

IO.inspect(converted, label: "converted --")

assert Utils.str_occurence(converted, @eyebrow_class) == 0
assert Utils.str_occurence(converted, @footer_class) == 1
end
Expand Down
2 changes: 1 addition & 1 deletion test/helper/converter/editor_to_html_test/list_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ defmodule GroupherServer.Test.Helper.Converter.EditorToHTML.List do

describe "[list block unit]" do
defp set_items(mode, items) do
editor_json = %{
%{
"time" => 1_567_250_876_713,
"blocks" => [
%{
Expand Down
9 changes: 9 additions & 0 deletions test/helper/converter/editor_to_html_test/table_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ defmodule GroupherServer.Test.Helper.Converter.EditorToHTML.Table do
},
%{block: "table", field: "items", message: "should be: list", value: "bb"}
]

editor_json = set_items(-2, "bb")
{:ok, editor_string} = Jason.encode(editor_json)
{:error, err_msg} = Parser.to_html(editor_string)

assert err_msg == [
%{block: "table", field: "columnCount", message: "min size: 2", value: -2},
%{block: "table", field: "items", message: "should be: list", value: "bb"}
]
end
end
end
158 changes: 158 additions & 0 deletions test/helper/validator/schema_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
defmodule GroupherServer.Test.Helper.Validator.Schema do
@moduledoc false

use GroupherServerWeb.ConnCase, async: true

alias Helper.Validator.Schema

describe "[basic schema]" do
test "string with options" do
schema = %{"text" => [:string, required: false]}
data = %{"no_exsit" => "text"}
assert {:ok, _} = Schema.cast(schema, data)

schema = %{"text" => [:string, required: true]}
data = %{"no_exsit" => "text"}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "should be: string", value: nil}]

schema = %{"text" => [:string, required: true]}
data = %{"text" => "text"}
assert {:ok, _} = Schema.cast(schema, data)

schema = %{"text" => [:string, min: 5]}
data = %{"text" => "text"}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "min size: 5", value: "text"}]

schema = %{"text" => [:string, required: false, min: 5]}
data = %{"text" => "text"}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "min size: 5", value: "text"}]

schema = %{"text" => [:string, min: 5]}
data = %{"no_exsit" => "text"}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "should be: string", value: nil}]

schema = %{"text" => [:string, required: true, min: 5]}
data = %{"no_exsit" => "text"}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "should be: string", value: nil}]

schema = %{"text" => [:string, required: true, min: "5"]}
data = %{"text" => "text"}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "unknow option: min: 5", value: "text"}]
# IO.inspect(Schema.cast(schema, data), label: "schema result")
end

test "number with options" do
schema = %{"text" => [:number, required: false]}
data = %{"no_exsit" => 1}
assert {:ok, _} = Schema.cast(schema, data)

schema = %{"text" => [:number, required: true]}
data = %{"no_exsit" => 1}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "should be: number", value: nil}]

schema = %{"text" => [:number, required: true]}
data = %{"text" => 1}
assert {:ok, _} = Schema.cast(schema, data)

schema = %{"text" => [:number, min: 5]}
data = %{"text" => 4}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "min size: 5", value: 4}]

schema = %{"text" => [:number, required: false, min: 5]}
data = %{"text" => 4}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "min size: 5", value: 4}]

schema = %{"text" => [:number, min: 5]}
data = %{"no_exsit" => 4}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "should be: number", value: nil}]

schema = %{"text" => [:number, required: true, min: 5]}
data = %{"no_exsit" => 1}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "should be: number", value: nil}]

# IO.inspect(Schema.cast(schema, data), label: "schema result")
# hello world
end

test "number with wrong option" do
schema = %{"text" => [:number, required: true, min: "5"]}
data = %{"text" => 1}

{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "unknow option: min: 5", value: 1}]

schema = %{"text" => [:number, required: true, no_exsit_option: "xxx"]}
data = %{"text" => 1}

{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "unknow option: no_exsit_option: xxx", value: 1}]
end

test "number with options edage case" do
schema = %{"text" => [:number, min: 2]}
data = %{"text" => "aa"}

{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "should be: number", value: "aa"}]
end

test "list with options" do
schema = %{"text" => [:list, required: false]}
data = %{"no_exsit" => []}
assert {:ok, _} = Schema.cast(schema, data)

schema = %{"text" => [:list, required: true]}
data = %{"no_exsit" => []}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "should be: list", value: nil}]

schema = %{"text" => [:list, required: true]}
data = %{"text" => []}
assert {:ok, _} = Schema.cast(schema, data)
end

test "boolean with options" do
schema = %{"text" => [:boolean, required: false]}
data = %{"no_exsit" => false}
assert {:ok, _} = Schema.cast(schema, data)

schema = %{"text" => [:boolean, required: true]}
data = %{"no_exsit" => false}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "should be: boolean", value: nil}]

schema = %{"text" => [:boolean, required: true]}
data = %{"text" => false}
assert {:ok, _} = Schema.cast(schema, data)
end

test "enum with options" do
schema = %{"text" => [enum: [1, 2, 3], required: false]}
data = %{"no_exsit" => false}
assert {:ok, _} = Schema.cast(schema, data)

schema = %{"text" => [enum: [1, 2, 3], required: true]}
data = %{"no_exsit" => false}
{:error, error} = Schema.cast(schema, data)
assert error == [%{field: "text", message: "should be: 1 | 2 | 3"}]

schema = %{"text" => [enum: [1, 2, 3]]}
data = %{"text" => 1}
assert {:ok, _} = Schema.cast(schema, data)

# IO.inspect(Schema.cast(schema, data), label: "schema result")
# hello world
end
end
end