write first test and let changeset errors return error json in controller

This commit is contained in:
Silas 2021-12-02 22:45:39 -05:00
parent 89c2a99283
commit d32dc8c2cb
Signed by: silentsilas
GPG Key ID: 4199EFB7DAA34349
7 changed files with 148 additions and 13 deletions

67
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,67 @@
{
"version": "2.0.0",
"tasks": [{
"label": "mix test",
"type": "shell",
"command": "mix",
"args": [
"test",
"--exclude",
"integration",
"--exclude",
"feature",
"--color"
],
"options": {
"cwd": "${workspaceRoot}",
"requireFiles": [
"test/**/test_helper.exs",
"test/**/*_test.exs"
]
},
"problemMatcher": "$mixTestFailure"
},
{
"label": "mix test file",
"type": "shell",
"command": "mix",
"args": [
"test",
"${relativeFile}",
"--color",
"--trace"
],
"options": {
"cwd": "${workspaceRoot}",
"requireFiles": [
"test/**/test_helper.exs",
"test/**/*_test.exs"
]
},
"problemMatcher": "$mixTestFailure"
},
{
"label": "mix test focused",
"type": "shell",
"command": "mix",
"args": [
"test",
"${relativeFile}:${lineNumber}",
"--color",
"--trace"
],
"options": {
"cwd": "${workspaceRoot}",
"requireFiles": [
"test/**/test_helper.exs",
"test/**/*_test.exs"
]
},
"problemMatcher": "$mixTestFailure",
"group": {
"kind": "test",
"isDefault": true
}
}
]
}

View File

@ -10,6 +10,8 @@ use Mix.Config
config :entendu, config :entendu,
ecto_repos: [Entendu.Repo] ecto_repos: [Entendu.Repo]
config :entendu, Entendu.Repo, migration_primary_key: [type: :uuid]
# Configures the endpoint # Configures the endpoint
config :entendu, EntenduWeb.Endpoint, config :entendu, EntenduWeb.Endpoint,
url: [host: "dev.intended.link"], url: [host: "dev.intended.link"],

View File

@ -2,6 +2,8 @@ defmodule Entendu.Links.Link do
use Ecto.Schema use Ecto.Schema
import Ecto.Changeset import Ecto.Changeset
@primary_key {:id, Ecto.UUID, autogenerate: true}
schema "links" do schema "links" do
field :burn_after_reading, :boolean, default: false field :burn_after_reading, :boolean, default: false
field :expires, :utc_datetime field :expires, :utc_datetime
@ -16,7 +18,13 @@ defmodule Entendu.Links.Link do
@doc false @doc false
def changeset(link, attrs) do def changeset(link, attrs) do
link link
|> cast(attrs, [:expires, :burn_after_reading, :filename, :filetype, :text_content, :file_content]) |> cast(attrs, [
|> validate_required([:expires, :burn_after_reading, :filename, :filetype]) :expires,
:burn_after_reading,
:filename,
:filetype,
:text_content,
:file_content
])
end end
end end

View File

@ -0,0 +1,10 @@
defmodule EntenduWeb.FallbackController do
use EntenduWeb, :controller
def call(conn, {:error, %Ecto.Changeset{} = changeset}) do
conn
|> put_status(:unprocessable_entity)
|> put_view(EntenduWeb.ChangesetView)
|> render("error.json", changeset: changeset)
end
end

View File

@ -9,27 +9,33 @@ defmodule EntenduWeb.LinkController do
alias Entendu.Links alias Entendu.Links
alias Links.Link alias Links.Link
alias Ecto.Changeset alias Ecto.Changeset
alias EntenduWeb.FallbackController
action_fallback(FallbackController)
def just_page(conn, _params) do def just_page(conn, _params) do
render(conn, "just.html") render(conn, "just.html")
end end
defparams first_step %{ defparams(
burn_after_reading: [field: :boolean, default: false], first_step(%{
expires: :utc_datetime, burn_after_reading: [field: :boolean, default: false],
filename: :string, expires: :utc_datetime,
filetype: :string, filename: :string,
text_content: :string, filetype: :string,
file_content: :string text_content: :string,
} file_content: :string
})
)
def just(conn, params) do def just(conn, params) do
with %Changeset{valid?: true} = changeset <- first_step(params), with %Changeset{valid?: true} = changeset <- first_step(params),
link_params <- Params.to_map(changeset), link_params <- Params.to_map(changeset),
{:ok, %Link{} = link} <- Links.create_link(link_params) do {:ok, %Link{} = link} <- Links.create_link(link_params) do
conn conn
|> put_status(:created)
|> assign(:link, link) |> assign(:link, link)
|> render("show_authorized", link: link) |> render("show_authorized.json", %{link: link})
end end
end end

View File

@ -0,0 +1,15 @@
defmodule EntenduWeb.ChangesetView do
use EntenduWeb, :view
def translate_errors(%Ecto.Changeset{} = changeset) do
Ecto.Changeset.traverse_errors(changeset, &translate_error/1)
end
def translate_errors(errors = %{}), do: errors
def render("error.json", %{changeset: changeset}) do
# When encoded, the changeset returns its errors
# as a JSON object. So we just pass it forward.
%{errors: translate_errors(changeset)}
end
end

View File

@ -0,0 +1,27 @@
defmodule EntenduWeb.ErrorViewTest do
use EntenduWeb.ConnCase, async: true
# Bring render/3 and render_to_string/3 for testing custom views
import Phoenix.View
test "renders 404.html" do
assert render_to_string(EntenduWeb.ErrorView, "404.html", []) == "Not Found"
end
test "just endpoint creates a link with valid attrs", %{conn: conn} do
params = %{
"text_content" => "some gibberish",
"filename" => "more gibberish"
}
conn = post(conn, Routes.link_path(conn, :just), params)
response = json_response(conn, 201)
assert %{
"id" => _link_id,
"text_content" => "some gibberish",
"filename" => "more gibberish"
} = response
end
end