From 8fa7eaaea3007dba95388091c1b9963fb07990e3 Mon Sep 17 00:00:00 2001 From: Jesse Dijkstra <mail@jessedijkstra.nl> Date: Fri, 24 Nov 2017 15:21:37 +0100 Subject: [PATCH] Use CellJS adapter --- lib/ex_cell/adapters/cell_js.ex | 12 ++- lib/ex_cell/base.ex | 44 +--------- lib/ex_cell/ex_cell.ex | 33 +++++++ test/ex_cell/adapters/cell_js_test.exs | 114 ++++++++++++++++++++----- test/ex_cell/base_test.exs | 35 -------- test/ex_cell/cell_test.exs | 71 +++++---------- test/ex_cell/ex_cell_test.exs | 30 +++++++ 7 files changed, 183 insertions(+), 156 deletions(-) delete mode 100644 test/ex_cell/base_test.exs diff --git a/lib/ex_cell/adapters/cell_js.ex b/lib/ex_cell/adapters/cell_js.ex index fb974e1..743953f 100644 --- a/lib/ex_cell/adapters/cell_js.ex +++ b/lib/ex_cell/adapters/cell_js.ex @@ -6,11 +6,8 @@ defmodule ExCell.Adapters.CellJS do def data_attribute(name, data \\ [], params \\ %{}) def data_attribute(name, data, params) when is_nil(data), do: data_attribute(name, [], params) - - def data_attribute(name, data, params) when is_list(data) do - data - |> Keyword.merge(cell: name, cell_params: Poison.encode!(params)) - end + def data_attribute(name, data, params) when is_list(data), do: + Keyword.merge(data, cell: name, cell_params: Poison.encode!(params)) def attributes(name, attributes \\ [], params \\ %{}) do Keyword.put( @@ -24,10 +21,11 @@ defmodule ExCell.Adapters.CellJS do name: name, attributes: attributes, params: params, - tag: tag, - closing_tag: closing_tag, content: content }) do + {tag, attributes} = Keyword.pop(attributes, :tag, :div) + {closing_tag, attributes} = Keyword.pop(attributes, :closing_tag, true) + attributes = attributes(name, attributes, params) case closing_tag do diff --git a/lib/ex_cell/base.ex b/lib/ex_cell/base.ex index 2c77c2b..3ba0dfc 100644 --- a/lib/ex_cell/base.ex +++ b/lib/ex_cell/base.ex @@ -1,27 +1,7 @@ defmodule ExCell.Base do - @moduledoc false - @dialyzer [{:no_match, relative_name: 2}] - - def relative_name(module, namespace) do - parts = case namespace do - nil -> Module.split(module) - _ -> ExCell.module_relative_to(module, namespace) - end - - Enum.join(parts, "-") - end - - def class_attribute(name, class) do - [name, class] - |> List.flatten - |> Enum.reject(&is_nil/1) - |> Enum.join(" ") - end - defmacro __using__(opts \\ []) do quote do import ExCell.View - import ExCell.Base @adapter unquote(opts[:adapter] || ExCell.Adapters.CellJS) @namespace unquote(opts[:namespace]) @@ -38,7 +18,8 @@ defmodule ExCell.Base do iex(1)> User.AvatarCell.name() "User-AvatarCell" """ - def name, do: relative_name(__MODULE__, @namespace) + def __adapter__, do: @adapter + def name, do: ExCell.relative_name(__MODULE__, @namespace) @doc """ Generates the CSS class name based on the cell name. Can be overriden @@ -135,26 +116,7 @@ defmodule ExCell.Base do def container(%{} = params, options) when is_list(options), do: container(params, options, [do: nil]) def container(%{} = params, options, [do: content]) when is_list(options), do: - @adapter.container(adapter_options(params, options, content)) - - def adapter_options(params \\ %{}, attributes \\ [], content \\ nil) do - {tag, attributes} = Keyword.pop(attributes, :tag, :div) - {closing_tag, attributes} = Keyword.pop(attributes, :closing_tag, true) - {cell_name, attributes} = - Keyword.pop(attributes, :cell_name, cell_name()) - - class_attribute = - class_attribute(class_name(), Keyword.get(attributes, :class)) - - %{ - name: cell_name, - attributes: Keyword.put(attributes, :class, class_attribute), - params: params(params), - tag: tag, - closing_tag: closing_tag, - content: content - } - end + ExCell.container(__MODULE__, params, options, [do: content]) defoverridable [class_name: 0, cell_name: 0, params: 0] end diff --git a/lib/ex_cell/ex_cell.ex b/lib/ex_cell/ex_cell.ex index becc733..b8036ce 100644 --- a/lib/ex_cell/ex_cell.ex +++ b/lib/ex_cell/ex_cell.ex @@ -1,5 +1,6 @@ defmodule ExCell do @moduledoc false + @dialyzer [{:no_match, relative_name: 2}] def module_relative_to(module, relative_to) do module @@ -12,4 +13,36 @@ defmodule ExCell do |> Application.get_env(__MODULE__, []) |> Keyword.get(keyword, fallback) end + + + def relative_name(module, namespace) do + parts = case namespace do + nil -> Module.split(module) + _ -> ExCell.module_relative_to(module, namespace) + end + + Enum.join(parts, "-") + end + + def class_name(name, classes) do + [name, classes] + |> List.flatten + |> Enum.reject(&is_nil/1) + |> Enum.join(" ") + end + + def container(module, params, attributes, [do: content]) do + options(module, params, attributes, content) + |> module.__adapter__().container() + end + + def options(module, params, attributes, content) do + %{ + name: module.cell_name(), + params: module.params(params), + attributes: Keyword.put(attributes, :class, + class_name(module.class_name(), Keyword.get(attributes, :class))), + content: content + } + end end diff --git a/test/ex_cell/adapters/cell_js_test.exs b/test/ex_cell/adapters/cell_js_test.exs index 1884c33..b20347f 100644 --- a/test/ex_cell/adapters/cell_js_test.exs +++ b/test/ex_cell/adapters/cell_js_test.exs @@ -4,13 +4,8 @@ defmodule ExCell.Adapters.CellJSTest do import Phoenix.HTML alias Phoenix.HTML.Tag - alias ExCell.Cell alias ExCell.Adapters.CellJS - defmodule MockCell do - use Cell, namespace: ExCell.Adapters.CellJSTest - end - describe "attributes/3" do test "it rejects nil values" do assert CellJS.attributes(nil, [], %{}) == @@ -55,48 +50,121 @@ defmodule ExCell.Adapters.CellJSTest do describe "container/1" do test "defaults to a :div as tag" do - assert safe_to_string(CellJS.container(MockCell.adapter_options())) + attributes = %{ + name: "MockCell", + attributes: [ + class: "MockCell" + ], + params: %{}, + content: nil + } + + assert safe_to_string(CellJS.container(attributes)) == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\"></div>" end test "custom tag" do - assert safe_to_string(CellJS.container(MockCell.adapter_options(%{}, tag: :p))) + attributes = %{ + name: "MockCell", + attributes: [ + tag: :p, + class: "MockCell" + ], + params: %{}, + content: nil + } + + assert safe_to_string(CellJS.container(attributes)) == "<p class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\"></p>" end test "content" do - assert safe_to_string(CellJS.container(MockCell.adapter_options(%{}, [], "TestContent"))) + attributes = %{ + name: "MockCell", + attributes: [ + class: "MockCell" + ], + params: %{}, + content: "TestContent" + } + + assert safe_to_string(CellJS.container(attributes)) == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\">TestContent</div>" end test "unsafe content" do - assert safe_to_string( - CellJS.container(MockCell.adapter_options(%{}, [], Tag.content_tag(:div, "TestContent"))) - ) == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\"><div>TestContent</div></div>" + attributes = %{ + name: "MockCell", + attributes: [ + class: "MockCell" + ], + params: %{}, + content: Tag.content_tag(:div, "TestContent") + } + + assert safe_to_string(CellJS.container(attributes)) + == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\"><div>TestContent</div></div>" end test "cell params" do - assert safe_to_string( - CellJS.container(MockCell.adapter_options(%{ foo: "bar" })) - ) == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{"foo":"bar"}\"></div>" + attributes = %{ + name: "MockCell", + attributes: [ + class: "MockCell" + ], + params: %{ + foo: "bar" + }, + content: nil + } + + assert safe_to_string(CellJS.container(attributes)) + == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{"foo":"bar"}\"></div>" end test "attributes" do - assert safe_to_string( - CellJS.container(MockCell.adapter_options(%{}, foo: "bar")) - ) == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\" foo=\"bar\"></div>" + attributes = %{ + name: "MockCell", + attributes: [ + class: "MockCell", + foo: "bar" + ], + params: %{}, + content: nil + } + + assert safe_to_string(CellJS.container(attributes)) + == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\" foo=\"bar\"></div>" end test "data attributes" do - assert safe_to_string( - CellJS.container(MockCell.adapter_options(%{}, data: [foo: "bar"])) - ) == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\" data-foo=\"bar\"></div>" + attributes = %{ + name: "MockCell", + attributes: [ + class: "MockCell", + data: [foo: "bar"] + ], + params: %{}, + content: nil + } + + assert safe_to_string(CellJS.container(attributes)) + == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\" data-foo=\"bar\"></div>" end test "no closing tag" do - assert safe_to_string( - CellJS.container(MockCell.adapter_options(%{}, closing_tag: false, data: [foo: "bar"])) - ) == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\" data-foo=\"bar\">" + attributes = %{ + name: "MockCell", + attributes: [ + class: "MockCell", + closing_tag: false + ], + params: %{}, + content: nil + } + + assert safe_to_string(CellJS.container(attributes)) + == "<div class=\"MockCell\" data-cell=\"MockCell\" data-cell-params=\"{}\">" end end end diff --git a/test/ex_cell/base_test.exs b/test/ex_cell/base_test.exs deleted file mode 100644 index cdab6a4..0000000 --- a/test/ex_cell/base_test.exs +++ /dev/null @@ -1,35 +0,0 @@ -defmodule ExCell.BaseTest do - use ExUnit.Case - - alias ExCell.Base - - describe "relative_name/2" do - test "returns the module name" do - assert Base.relative_name(MockCell, nil) == "MockCell" - end - - test "returns the relative module name" do - assert Base.relative_name(Bar.MockCell, Bar) == "MockCell" - end - - test "returns the relative module name with dashes for nested cells" do - assert Base.relative_name(Bar.MockCell, nil) == "Bar-MockCell" - end - end - - describe "class_attribute/2" do - test "adds the name" do - assert Base.class_attribute("Hello", "World") == - "Hello World" - end - - test "allows lists" do - assert Base.class_attribute(["Hello", "World"], ["Foo", "Bar"]) == - "Hello World Foo Bar" - end - - test "rejects nil" do - assert Base.class_attribute(nil, nil) == "" - end - end -end diff --git a/test/ex_cell/cell_test.exs b/test/ex_cell/cell_test.exs index 580a160..cf5e30a 100644 --- a/test/ex_cell/cell_test.exs +++ b/test/ex_cell/cell_test.exs @@ -2,16 +2,23 @@ defmodule ExCell.CellTest do use ExUnit.Case alias ExCell.Cell + defmodule MockAdapter do + def container(options), do: options + end + defmodule Foo.MockCell do - use Cell, namespace: Foo + use Cell, namespace: Foo, + adapter: MockAdapter end defmodule Foo.Bar.MockCell do - use Cell, namespace: Foo + use Cell, namespace: Foo, + adapter: MockAdapter end defmodule Foo.MockCellWithOverridables do - use Cell, namespace: Foo + use Cell, namespace: Foo, + adapter: MockAdapter def params, do: %{foo: "Bar"} def class_name, do: "Bar-" <> name() @@ -73,100 +80,64 @@ defmodule ExCell.CellTest do end end - describe "adapter_options/3" do + describe "container/3" do test "without arguments" do - assert MockCell.adapter_options() == %{ + assert MockCell.container() == %{ name: "MockCell", attributes: [ class: "MockCell" ], - closing_tag: true, content: nil, - params: %{}, - tag: :div + params: %{} } end test "with overrideables" do - assert MockCellWithOverridables.adapter_options() == %{ + assert MockCellWithOverridables.container() == %{ name: "World-MockCellWithOverridables", attributes: [ class: "Bar-MockCellWithOverridables" ], - closing_tag: true, content: nil, params: %{ foo: "Bar" - }, - tag: :div - } - end - - test "with custom tag" do - assert MockCell.adapter_options(%{}, tag: :p) == %{ - name: "MockCell", - attributes: [ - class: "MockCell" - ], - closing_tag: true, - content: nil, - params: %{}, - tag: :p + } } end test "with content" do - assert MockCell.adapter_options(%{}, [], "TestContent") == %{ + assert MockCell.container(%{}, [], [do: "TestContent"]) == %{ name: "MockCell", attributes: [ class: "MockCell" ], - closing_tag: true, content: "TestContent", - params: %{}, - tag: :div + params: %{} } end test "with cell params" do - assert MockCell.adapter_options(%{ foo: "bar" }) == %{ + assert MockCell.container(%{ foo: "bar" }) == %{ name: "MockCell", attributes: [ class: "MockCell" ], - closing_tag: true, content: nil, params: %{ foo: "bar" - }, - tag: :div + } } end test "with custom atttributes" do - assert MockCell.adapter_options(%{}, foo: "bar") == %{ + assert MockCell.container(%{}, foo: "bar") == %{ name: "MockCell", attributes: [ class: "MockCell", foo: "bar" ], - closing_tag: true, - content: nil, - params: %{}, - tag: :div - } - end - - test "without closing tag" do - assert MockCell.adapter_options(%{}, closing_tag: false) == %{ - name: "MockCell", - attributes: [ - class: "MockCell" - ], - closing_tag: false, content: nil, - params: %{}, - tag: :div + params: %{} } end end diff --git a/test/ex_cell/ex_cell_test.exs b/test/ex_cell/ex_cell_test.exs index a29d19c..d0278b8 100644 --- a/test/ex_cell/ex_cell_test.exs +++ b/test/ex_cell/ex_cell_test.exs @@ -24,4 +24,34 @@ defmodule ExCellTest do assert ExCell.config(:hello, :world) == :world end end + + describe "relative_name/2" do + test "returns the module name" do + assert ExCell.relative_name(MockCell, nil) == "MockCell" + end + + test "returns the relative module name" do + assert ExCell.relative_name(Bar.MockCell, Bar) == "MockCell" + end + + test "returns the relative module name with dashes for nested cells" do + assert ExCell.relative_name(Bar.MockCell, nil) == "Bar-MockCell" + end + end + + describe "class_name/2" do + test "adds the name" do + assert ExCell.class_name("Hello", "World") == + "Hello World" + end + + test "allows lists" do + assert ExCell.class_name(["Hello", "World"], ["Foo", "Bar"]) == + "Hello World Foo Bar" + end + + test "rejects nil" do + assert ExCell.class_name(nil, nil) == "" + end + end end