Skip to content

Commit

Permalink
Add integration test on mix torch.gen.html
Browse files Browse the repository at this point in the history
  • Loading branch information
danielberkompas committed Apr 25, 2018
1 parent 5c083f9 commit 1b36b70
Show file tree
Hide file tree
Showing 38 changed files with 578 additions and 1,432 deletions.
62 changes: 15 additions & 47 deletions lib/mix/tasks/torch.gen.html.ex
Original file line number Diff line number Diff line change
@@ -1,60 +1,30 @@
defmodule Mix.Tasks.Torch.Gen.Html do
@moduledoc """
Light wrapper module around phx.gen.context. Installs and uninstalls context
templates around running the phoenix generator.
Light wrapper module around `mix phx.gen.html` which generates slightly
modified HTML.
## Parameters
Takes all the same params as the regualar phx generators.
# TODO
Takes all the same params as the `phx.gen.html` task.
## Example
mix torch.gen.context Accounts User users --no-schema
mix torch.gen.html Accounts User users --no-schema
"""

import Torch.Config, only: [template_format: 0]
@commands ~w[phx.gen.html phx.gen.context]

def run([context | args]) do
format = template_format()
def run(args) do
%{format: format} = Mix.Torch.parse_config!("torch.gen.html", args)

# Copy over phoenix generator html templates
Mix.Torch.copy_from([:torch], "priv/templates/#{format}/phx.gen.html", "", [], [
{:exs, "controller_test.exs", "priv/templates/phx.gen.html/controller_test.exs"},
{:ex, "controller.ex", "priv/templates/phx.gen.html/controller.ex"},
{:eex, "edit.html.eex", "priv/templates/phx.gen.html/edit.html.eex"},
{:eex, "form.html.eex", "priv/templates/phx.gen.html/form.html.eex"},
{:eex, "index.html.eex", "priv/templates/phx.gen.html/index.html.eex"},
{:eex, "new.html.eex", "priv/templates/phx.gen.html/new.html.eex"},
{:eex, "show.html.eex", "priv/templates/phx.gen.html/show.html.eex"},
{:ex, "view.ex", "priv/templates/phx.gen.html/view.ex"}
])
# Inject the torch templates for the generator into the priv/
# directory so they will be picked up by the Phoenix generator
Enum.each(@commands, &Mix.Torch.inject_templates(&1, format))

# Copy over phoenix generator context templates
Mix.Torch.copy_from([:torch], "priv/templates/phx.gen.context", "", [], [
{:ex, "access_no_schema.ex", "priv/templates/phx.gen.context/access_no_schema.ex"},
{:ex, "context.ex", "priv/templates/phx.gen.context/context.ex"},
{:ex, "schema_access.ex", "priv/templates/phx.gen.context/schema_access.ex"},
{:exs, "test_cases.exs", "priv/templates/phx.gen.context/test_cases.exs"},
{:exs, "context_test.exs", "priv/templates/phx.gen.context/context_test.exs"}
])
# Run the Phoenix generator
Mix.Task.run("phx.gen.html", args)

Mix.Task.run("phx.gen.html", [context | args])

File.rm("priv/templates/phx.gen.html/controller_test.exs")
File.rm("priv/templates/phx.gen.html/controller.ex")
File.rm("priv/templates/phx.gen.html/edit.html.#{format}")
File.rm("priv/templates/phx.gen.html/form.html.#{format}")
File.rm("priv/templates/phx.gen.html/index.html.#{format}")
File.rm("priv/templates/phx.gen.html/new.html.#{format}")
File.rm("priv/templates/phx.gen.html/show.html.#{format}")
File.rm("priv/templates/phx.gen.html/view.ex")
File.rm("priv/templates/phx.gen.context/access_no_schema.ex")
File.rm("priv/templates/phx.gen.context/context.ex")
File.rm("priv/templates/phx.gen.context/schema_access.ex")
File.rm("priv/templates/phx.gen.context/test_cases.exs")
File.rm("priv/templates/phx.gen.context/context_test.exs")
# Remove the injected templates from priv/ so they will not
# affect future Phoenix generator commands
Enum.each(@commands, &Mix.Torch.remove_templates/1)

Mix.shell().info("""
Ensure the following is added to your endpoint.ex:
Expand All @@ -76,7 +46,5 @@ defmodule Mix.Tasks.Torch.Gen.Html do
<!-- nav links here -->
</nav>
""")

Mix.shell().info("\u{1F525} #{IO.ANSI.yellow()}Torch generated html for #{context}!\u{1F525}")
end
end
4 changes: 2 additions & 2 deletions lib/mix/tasks/torch.install.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ defmodule Mix.Tasks.Torch.Install do
def run(args) do
%{format: format, otp_app: otp_app} = Mix.Torch.parse_config!("torch.install", args)

Mix.Torch.copy_from([:torch], "priv/templates/#{format}", "", [], [
{:eex, "layout.html.#{format}", "lib/#{otp_app}_web/templates/layout/torch.html.#{format}"}
Mix.Torch.copy_from("priv/templates/#{format}", [
{"layout.html.#{format}", "lib/#{otp_app}_web/templates/layout/torch.html.#{format}"}
])
end
end
59 changes: 32 additions & 27 deletions lib/mix/torch.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ defmodule Mix.Torch do

alias Torch.Config

@doc false
def parse_config!(task, args) do
{opts, _, _} = OptionParser.parse(args, switches: [format: :string, app: :string])

Expand Down Expand Up @@ -41,35 +40,41 @@ defmodule Mix.Torch do
%{otp_app: otp_app, format: format}
end

@doc """
Copies files from source dir to target dir
according to the given map.
def copy_from(source_dir, mapping) when is_list(mapping) do
for {source_file_path, target_file_path} <- mapping do
contents =
[Application.app_dir(:torch), source_dir, source_file_path]
|> Path.join()
|> File.read!()

Files are evaluated against EEx according to
the given binding.
"""
def copy_from(apps, source_dir, target_dir, _binding, mapping) when is_list(mapping) do
roots = Enum.map(apps, &to_app_source(&1, source_dir))

for {_format, source_file_path, target_file_path} <- mapping do
source =
Enum.find_value(roots, fn root ->
source = Path.join(root, source_file_path)
if File.exists?(source), do: source
end) || raise "could not find #{source_file_path} in any of the sources"

target = Path.join(target_dir, target_file_path)
Mix.Generator.create_file(target_file_path, contents)
end
end

contents = File.read!(source)
# case format do
# :eex -> EEx.eval_file(source, binding)
# _ -> File.read!(source)
# end
def inject_templates("phx.gen.html", format) do
copy_from("priv/templates/#{format}/phx.gen.html", [
{"controller_test.exs", "priv/templates/phx.gen.html/controller_test.exs"},
{"controller.ex", "priv/templates/phx.gen.html/controller.ex"},
{"edit.html.#{format}", "priv/templates/phx.gen.html/edit.html.#{format}"},
{"form.html.#{format}", "priv/templates/phx.gen.html/form.html.#{format}"},
{"index.html.#{format}", "priv/templates/phx.gen.html/index.html.#{format}"},
{"new.html.#{format}", "priv/templates/phx.gen.html/new.html.#{format}"},
{"show.html.#{format}", "priv/templates/phx.gen.html/show.html.#{format}"},
{"view.ex", "priv/templates/phx.gen.html/view.ex"}
])
end

Mix.Generator.create_file(target, contents)
end
def inject_templates("phx.gen.context", _format) do
copy_from("priv/templates/phx.gen.context", [
{"access_no_schema.ex", "priv/templates/phx.gen.context/access_no_schema.ex"},
{"context.ex", "priv/templates/phx.gen.context/context.ex"},
{"schema_access.ex", "priv/templates/phx.gen.context/schema_access.ex"},
{"test_cases.exs", "priv/templates/phx.gen.context/test_cases.exs"},
{"context_test.exs", "priv/templates/phx.gen.context/context_test.exs"}
])
end

defp to_app_source(path, source_dir) when is_binary(path), do: Path.join(path, source_dir)
defp to_app_source(app, source_dir) when is_atom(app), do: Application.app_dir(app, source_dir)
def remove_templates(template_dir) do
File.rm("priv/templates/#{template_dir}/")
end
end
160 changes: 160 additions & 0 deletions priv/templates/phx.gen.context/access_no_schema.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@

import Torch.Helpers, only: [sort: 1, paginate: 4]
import Filtrex.Type.Config

alias <%= inspect schema.module %>

@pagination [page_size: 15]
@pagination_distance 5

@doc """
Paginate the list of <%= schema.plural %> using filtrex
filters.
## Examples
iex> list_<%= schema.plural %>(%{})
%{<%= schema.plural %>: [%<%= inspect schema.alias %>{}], ...}
"""
@spec paginate_<%= schema.plural %>(map) :: {:ok, map} | {:error, any}
def paginate_<%= schema.plural %>(params \\ %{}) do
params =
params
|> Map.put_new("sort_direction", "desc")
|> Map.put_new("sort_field", "inserted_at")

{:ok, sort_direction} = Map.fetch(params, "sort_direction")
{:ok, sort_field} = Map.fetch(params, "sort_field")

with {:ok, filter} <- Filtrex.parse_params(filter_config(<%= inspect String.to_atom(schema.plural) %>), params["<%= schema.singular %>"] || %{}),
%Scrivener.Page{} = page <- do_paginate_<%= schema.plural %>(filter, params) do
{:ok,
%{
<%= schema.plural %>: page.entries,
page_number: page.page_number,
page_size: page.page_size,
total_pages: page.total_pages,
total_entries: page.total_entries,
distance: @pagination_distance,
sort_field: sort_field,
sort_direction: sort_direction
}
}
else
{:error, error} -> {:error, error}
error -> {:error, error}
end
end

defp do_paginate_<%= schema.plural %>(filter, params) do
<%= inspect schema.alias %>
|> Filtrex.query(filter)
|> order_by(^sort(params))
|> paginate(Repo, params, @pagination)
end

@doc """
Returns the list of <%= schema.plural %>.
## Examples
iex> list_<%= schema.plural %>()
[%<%= inspect schema.alias %>{}, ...]
"""
def list_<%= schema.plural %> do
Repo.all(<%= inspect schema.alias %>)
end

@doc """
Gets a single <%= schema.singular %>.
Raises `Ecto.NoResultsError` if the <%= schema.human_singular %> does not exist.
## Examples
iex> get_<%= schema.singular %>!(123)
%<%= inspect schema.alias %>{}
iex> get_<%= schema.singular %>!(456)
** (Ecto.NoResultsError)
"""
def get_<%= schema.singular %>!(id), do: Repo.get!(<%= inspect schema.alias %>, id)

@doc """
Creates a <%= schema.singular %>.
## Examples
iex> create_<%= schema.singular %>(%{field: value})
{:ok, %<%= inspect schema.alias %>{}}
iex> create_<%= schema.singular %>(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def create_<%= schema.singular %>(attrs \\ %{}) do
%<%= inspect schema.alias %>{}
|> <%= inspect schema.alias %>.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a <%= schema.singular %>.
## Examples
iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: new_value})
{:ok, %<%= inspect schema.alias %>{}}
iex> update_<%= schema.singular %>(<%= schema.singular %>, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
def update_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>, attrs) do
<%= schema.singular %>
|> <%= inspect schema.alias %>.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a <%= inspect schema.alias %>.
## Examples
iex> delete_<%= schema.singular %>(<%= schema.singular %>)
{:ok, %<%= inspect schema.alias %>{}}
iex> delete_<%= schema.singular %>(<%= schema.singular %>)
{:error, %Ecto.Changeset{}}
"""
def delete_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>) do
Repo.delete(<%= schema.singular %>)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking <%= schema.singular %> changes.
## Examples
iex> change_<%= schema.singular %>(<%= schema.singular %>)
%Ecto.Changeset{source: %<%= inspect schema.alias %>{}}
"""
def change_<%= schema.singular %>(%<%= inspect schema.alias %>{} = <%= schema.singular %>) do
<%= inspect schema.alias %>.changeset(<%= schema.singular %>, %{})
end

defp filter_config(<%= inspect String.to_atom(schema.plural) %>) do
defconfig do
<%= for {name, type} <- schema.attrs do %><%= cond do %>
<% type in [:string, :text] -> %>text <%= inspect name %>
<% type in [:integer, :number] -> %>number <%= inspect name %>
<% type in [:naive_datetime, :utc_datetime, :datetime, :date] -> %>date <%= inspect name %>
<% type in [:boolean] -> %>boolean <%= inspect name %>
<% true -> %> #TODO add config for <%= name %> of type <%= type %>
<% end %><% end %>
end
end
8 changes: 8 additions & 0 deletions priv/templates/phx.gen.context/context.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
defmodule <%= inspect context.module %> do
@moduledoc """
The <%= context.name %> context.
"""

import Ecto.Query, warn: false
alias <%= inspect schema.repo %>
end
5 changes: 5 additions & 0 deletions priv/templates/phx.gen.context/context_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
defmodule <%= inspect context.module %>Test do
use <%= inspect context.base_module %>.DataCase

alias <%= inspect context.module %>
end
Loading

0 comments on commit 1b36b70

Please sign in to comment.