Compare commits
13
Commits
6300a1a8b7
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a3c22dab1 | ||
|
|
38e1e03b26 | ||
|
|
9e22e1bfde | ||
|
|
ddf54a9264 | ||
|
|
d0646b93f9 | ||
|
|
74136c7fa7 | ||
|
|
8ddb7da76e | ||
|
|
158dcce49b | ||
|
|
00467d249a | ||
|
|
15d12bd937 | ||
|
|
d3c3e210d5 | ||
|
|
1e15bc3603 | ||
|
|
d2f8543fdd |
@@ -9,6 +9,7 @@ environment:
|
|||||||
DATABASE_HOST: postgres
|
DATABASE_HOST: postgres
|
||||||
DATABASE_PORT: 5432
|
DATABASE_PORT: 5432
|
||||||
SECRET_KEY_BASE: TestSecretKeycRZ1H45gfdAsdf8DIb45df4664mRCruzwVEF68wosddfg324ost
|
SECRET_KEY_BASE: TestSecretKeycRZ1H45gfdAsdf8DIb45df4664mRCruzwVEF68wosddfg324ost
|
||||||
|
SELENIUM_REMOTE_URL: http://standalone-firefox:4444/wd/hub/
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: install dependencies
|
- name: install dependencies
|
||||||
@@ -49,4 +50,6 @@ services:
|
|||||||
POSTGRES_DB: link_shortener_dev
|
POSTGRES_DB: link_shortener_dev
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
|
- name: standalone-firefox
|
||||||
|
image: selenium/standalone-firefox:129.0
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -21,7 +21,7 @@ config :link_shortener, LinkShortener.Repo,
|
|||||||
config :link_shortener, LinkShortenerWeb.Endpoint,
|
config :link_shortener, LinkShortenerWeb.Endpoint,
|
||||||
http: [ip: {127, 0, 0, 1}, port: 4002],
|
http: [ip: {127, 0, 0, 1}, port: 4002],
|
||||||
secret_key_base: System.get_env("SECRET_KEY_BASE"),
|
secret_key_base: System.get_env("SECRET_KEY_BASE"),
|
||||||
server: false
|
server: true
|
||||||
|
|
||||||
# In test we don't send emails
|
# In test we don't send emails
|
||||||
config :link_shortener, LinkShortener.Mailer, adapter: Swoosh.Adapters.Test
|
config :link_shortener, LinkShortener.Mailer, adapter: Swoosh.Adapters.Test
|
||||||
@@ -38,3 +38,13 @@ config :phoenix, :plug_init_mode, :runtime
|
|||||||
# Enable helpful, but potentially expensive runtime checks
|
# Enable helpful, but potentially expensive runtime checks
|
||||||
config :phoenix_live_view,
|
config :phoenix_live_view,
|
||||||
enable_expensive_runtime_checks: true
|
enable_expensive_runtime_checks: true
|
||||||
|
|
||||||
|
config :wallaby,
|
||||||
|
otp_app: :link_shortener,
|
||||||
|
screenshot_on_failure: true,
|
||||||
|
screenshot_dir: "screenshots",
|
||||||
|
driver: Wallaby.Selenium,
|
||||||
|
selenium: [
|
||||||
|
remote_url: System.get_env("SELENIUM_REMOTE_URL", "http://localhost:4444/wd/hub/")
|
||||||
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,28 @@ defmodule LinkShortener.Generators.LinkWithRandomShorten do
|
|||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Generate a Link with random shorten with the length.
|
Generate a Link with random shorten with the length.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
• :is_atom_based (boolean, true by default) - if a map is
|
||||||
|
atom-based, then a key for shorten will be :shorten, else
|
||||||
|
"shorten".
|
||||||
|
• :length (integer, 10 by default) - the length for
|
||||||
|
the shorten.
|
||||||
|
• :generator (function) - the shorten is generated by the
|
||||||
|
generator function.
|
||||||
|
LinkShortener.Generators.SafeString.generate/1 by default.
|
||||||
"""
|
"""
|
||||||
def generate_one(attrs, length \\ 10, generator \\ &SafeString.generate/1) do
|
@spec generate_one(map(), is_atom_based: boolean(), length: integer(), generator: function()) ::
|
||||||
Map.put(attrs, :shorten, generator.(length))
|
[map()]
|
||||||
|
def generate_one(attrs, opts \\ []) do
|
||||||
|
is_atom_based = Keyword.get(opts, :is_atom_based, true)
|
||||||
|
length = Keyword.get(opts, :length, 10)
|
||||||
|
generator = Keyword.get(opts, :generator, &SafeString.generate/1)
|
||||||
|
|
||||||
|
if is_atom_based do
|
||||||
|
Map.put(attrs, :shorten, generator.(length))
|
||||||
|
else
|
||||||
|
Map.put(attrs, "shorten", generator.(length))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,11 +5,32 @@ defmodule LinkShortener.Links do
|
|||||||
alias LinkShortener.Repo
|
alias LinkShortener.Repo
|
||||||
alias LinkShortener.Links.Link
|
alias LinkShortener.Links.Link
|
||||||
alias LinkShortener.Generators.LinkWithRandomShorten, as: LinkGenerator
|
alias LinkShortener.Generators.LinkWithRandomShorten, as: LinkGenerator
|
||||||
|
alias LinkShortener.Accounts.User
|
||||||
|
|
||||||
def new_one(), do: Link.changeset(%Link{}, %{})
|
def new_one(), do: Link.changeset(%Link{}, %{})
|
||||||
|
|
||||||
def create_one(attrs, length \\ 10, generator \\ &LinkGenerator.generate_one/2) do
|
@doc """
|
||||||
generator.(attrs, length)
|
Create a Link with random shorten with the length.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
• :is_atom_based (boolean, true by default) - if a map is
|
||||||
|
atom-based, then a key for shorten will be :shorten, else
|
||||||
|
"shorten".
|
||||||
|
• :length (integer, 10 by default) - the length for
|
||||||
|
the shorten.
|
||||||
|
• :generator (function) - the shorten is generated by the
|
||||||
|
generator function.
|
||||||
|
LinkShortener.Generators.LinkWithRandomShorten.generate_one/2 by
|
||||||
|
default.
|
||||||
|
"""
|
||||||
|
@spec create_one(map(), [is_atom_based: boolean(), length: integer(), generator: function()]) ::
|
||||||
|
[map()]
|
||||||
|
def create_one(attrs, opts \\ []) do
|
||||||
|
is_atom_based = Keyword.get(opts, :is_atom_based, true)
|
||||||
|
length = Keyword.get(opts, :length, 10)
|
||||||
|
generator = Keyword.get(opts, :generator, &LinkGenerator.generate_one/2)
|
||||||
|
|
||||||
|
generator.(attrs, is_atom_based: is_atom_based, length: length)
|
||||||
|> insert_one()
|
|> insert_one()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -49,9 +70,15 @@ defmodule LinkShortener.Links do
|
|||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit_one(%Link{} = link) do
|
def get_all_by_user(%User{id: user_id} = user) do
|
||||||
|
from(Link)
|
||||||
|
|> where([l], l.user_id == ^user_id)
|
||||||
|
|> Repo.all()
|
||||||
|
end
|
||||||
|
|
||||||
|
def edit_one(%Link{} = link, attrs \\ %{}) do
|
||||||
link
|
link
|
||||||
|> Link.changeset(%{})
|
|> Link.changeset(attrs)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_one(%Link{} = link, changes) do
|
def update_one(%Link{} = link, changes) do
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-4 font-semibold leading-6 text-zinc-900">
|
<div class="flex items-center gap-4 font-semibold leading-6 text-zinc-900">
|
||||||
<a href="#" class="hover:text-zinc-700">
|
<a href="/links" class="hover:text-zinc-700">
|
||||||
Links
|
Links
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ defmodule LinkShortenerWeb.Endpoint do
|
|||||||
]
|
]
|
||||||
|
|
||||||
socket "/live", Phoenix.LiveView.Socket,
|
socket "/live", Phoenix.LiveView.Socket,
|
||||||
websocket: [connect_info: [session: @session_options]],
|
websocket: [connect_info: [:user_agent, session: @session_options]],
|
||||||
longpoll: [connect_info: [session: @session_options]]
|
longpoll: [connect_info: [session: @session_options]]
|
||||||
|
|
||||||
# Serve at "/" the static files from "priv/static" directory.
|
# Serve at "/" the static files from "priv/static" directory.
|
||||||
|
|||||||
@@ -0,0 +1,146 @@
|
|||||||
|
defmodule LinkShortenerWeb.LinkLive.FormComponent do
|
||||||
|
use LinkShortenerWeb, :live_component
|
||||||
|
|
||||||
|
alias LinkShortener.Links
|
||||||
|
|
||||||
|
attr :is_checked, :boolean, default: true
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def render(assigns) do
|
||||||
|
~H"""
|
||||||
|
<div>
|
||||||
|
<.header>
|
||||||
|
<%= @title %>
|
||||||
|
<:subtitle>Use this form to manage link records.</:subtitle>
|
||||||
|
</.header>
|
||||||
|
|
||||||
|
<.simple_form
|
||||||
|
for={@form}
|
||||||
|
id="link-form"
|
||||||
|
phx-target={@myself}
|
||||||
|
phx-change="validate"
|
||||||
|
phx-submit="save"
|
||||||
|
>
|
||||||
|
<.input field={@form[:name]} type="text" label="Name" placeholder="Enter a name here" />
|
||||||
|
<.input field={@form[:url]} type="text" label="Url" placeholder="Enter an url here" />
|
||||||
|
|
||||||
|
<%= if @is_checked and @action == :new do %>
|
||||||
|
<.label>Shorten</.label>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= unless @is_checked and @action != :edit do %>
|
||||||
|
<.input
|
||||||
|
field={@form[:shorten]}
|
||||||
|
type="text"
|
||||||
|
label="Shorten"
|
||||||
|
placeholder="Enter a shorten here"
|
||||||
|
/>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= if @action == :new do %>
|
||||||
|
<label class="inline-flex items-center cursor-pointer">
|
||||||
|
<.input
|
||||||
|
id="random-toggle"
|
||||||
|
field={@form[:toggle]}
|
||||||
|
type="checkbox"
|
||||||
|
label="Random shorten"
|
||||||
|
checked={@is_checked}
|
||||||
|
phx-click="toggle"
|
||||||
|
phx-target={@myself}
|
||||||
|
phx-value-checked={!@is_checked}
|
||||||
|
class="peer sr-only"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<:actions>
|
||||||
|
<.button phx-disable-with="Saving...">Save Link</.button>
|
||||||
|
</:actions>
|
||||||
|
</.simple_form>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def update(%{link: link} = assigns, socket) do
|
||||||
|
{:ok,
|
||||||
|
socket
|
||||||
|
|> assign(assigns)
|
||||||
|
|> assign_new(:form, fn ->
|
||||||
|
to_form(Links.edit_one(link))
|
||||||
|
end)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_event("validate", %{"link" => link_params}, socket) do
|
||||||
|
link_params = with_user_id(link_params, socket.assigns.current_user)
|
||||||
|
changeset = Links.edit_one(socket.assigns.link, link_params)
|
||||||
|
{:noreply, assign(socket, form: to_form(changeset, action: :validate))}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_event("toggle", params, socket) do
|
||||||
|
is_checked = Map.get(params, "value", "false") == "true"
|
||||||
|
{:noreply, assign(socket, :is_checked, is_checked)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event("save", %{"link" => link_params}, socket) do
|
||||||
|
save_link(socket, socket.assigns.action, link_params)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp save_link(socket, :edit, link_params) do
|
||||||
|
case Links.update_one(socket.assigns.link, link_params) do
|
||||||
|
{:ok, link} ->
|
||||||
|
notify_parent({:saved, link})
|
||||||
|
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> put_flash(:info, "Link updated successfully")
|
||||||
|
|> push_patch(to: socket.assigns.patch)}
|
||||||
|
|
||||||
|
{:error, %Ecto.Changeset{} = changeset} ->
|
||||||
|
{:noreply, assign(socket, form: to_form(changeset))}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp save_link(socket, :new, link_params) do
|
||||||
|
{is_random_string, link_params} = Map.pop(link_params, "toggle")
|
||||||
|
is_random = is_random_string == "true"
|
||||||
|
|
||||||
|
link_params =
|
||||||
|
link_params
|
||||||
|
|> with_user_id(socket.assigns.current_user)
|
||||||
|
|
||||||
|
case create_link(link_params, is_random) do
|
||||||
|
{:ok, link} ->
|
||||||
|
notify_parent({:saved, link})
|
||||||
|
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> put_flash(:info, "Link created successfully")
|
||||||
|
|> push_patch(to: socket.assigns.patch)}
|
||||||
|
|
||||||
|
{:error, %Ecto.Changeset{} = changeset} ->
|
||||||
|
{:noreply, assign(socket, form: to_form(changeset))}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp create_link(link_params, is_shorten_random) do
|
||||||
|
if is_shorten_random do
|
||||||
|
Links.create_one(link_params, is_atom_based: false)
|
||||||
|
else
|
||||||
|
Links.insert_one(link_params)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp notify_parent(msg), do: send(self(), {__MODULE__, msg})
|
||||||
|
|
||||||
|
defp with_user_id(params, current_user) do
|
||||||
|
if Map.has_key?(params, "user_id") do
|
||||||
|
params
|
||||||
|
else
|
||||||
|
params
|
||||||
|
|> Map.put("user_id", current_user.id)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
defmodule LinkShortenerWeb.LinkLive.Index do
|
||||||
|
use LinkShortenerWeb, :live_view
|
||||||
|
|
||||||
|
alias LinkShortener.Links
|
||||||
|
alias LinkShortener.Links.Link
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def mount(_params, _session, socket) do
|
||||||
|
current_user = socket.assigns.current_user
|
||||||
|
is_random_shorten_by_default = true
|
||||||
|
|
||||||
|
{:ok,
|
||||||
|
socket
|
||||||
|
|> stream(:links, Links.get_all_by_user(current_user))
|
||||||
|
|> assign(:is_random_shorten_by_default, is_random_shorten_by_default)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_params(params, _url, socket) do
|
||||||
|
{:noreply, apply_action(socket, socket.assigns.live_action, params)}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp apply_action(socket, :edit, %{"id" => id}) do
|
||||||
|
socket
|
||||||
|
|> assign(:page_title, "Edit Link")
|
||||||
|
|> assign(:link, Links.get_one!(id))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp apply_action(socket, :new, _params) do
|
||||||
|
socket
|
||||||
|
|> assign(:page_title, "New Link")
|
||||||
|
|> assign(:link, %Link{})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp apply_action(socket, :index, _params) do
|
||||||
|
socket
|
||||||
|
|> assign(:page_title, "Listing Links")
|
||||||
|
|> assign(:link, nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_info({LinkShortenerWeb.LinkLive.FormComponent, {:saved, link}}, socket) do
|
||||||
|
{:noreply, stream_insert(socket, :links, link)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_event("delete", %{"id" => id}, socket) do
|
||||||
|
link = Links.get_one!(id)
|
||||||
|
{:ok, _} = Links.delete_one(link)
|
||||||
|
|
||||||
|
{:noreply, stream_delete(socket, :links, link)}
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<.header>
|
||||||
|
Listing Links
|
||||||
|
<:actions>
|
||||||
|
<.link patch={~p"/links/new"}>
|
||||||
|
<.button>New Link</.button>
|
||||||
|
</.link>
|
||||||
|
</:actions>
|
||||||
|
</.header>
|
||||||
|
|
||||||
|
<.table
|
||||||
|
id="links"
|
||||||
|
rows={@streams.links}
|
||||||
|
row_click={fn {_id, link} -> JS.navigate(~p"/links/#{link}") end}
|
||||||
|
>
|
||||||
|
<:col :let={{_id, link}} label="Name"><%= link.name %></:col>
|
||||||
|
<:col :let={{_id, link}} label="Url"><%= link.url %></:col>
|
||||||
|
<:col :let={{_id, link}} label="Shorten"><%= link.shorten %></:col>
|
||||||
|
<:action :let={{_id, link}}>
|
||||||
|
<div class="sr-only">
|
||||||
|
<.link navigate={~p"/links/#{link}"}>Show</.link>
|
||||||
|
</div>
|
||||||
|
<.link patch={~p"/links/#{link}/edit"}>Edit</.link>
|
||||||
|
</:action>
|
||||||
|
<:action :let={{id, link}}>
|
||||||
|
<.link
|
||||||
|
phx-click={JS.push("delete", value: %{id: link.id}) |> hide("##{id}")}
|
||||||
|
data-confirm="Are you sure?"
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</.link>
|
||||||
|
</:action>
|
||||||
|
</.table>
|
||||||
|
|
||||||
|
<.modal :if={@live_action in [:new, :edit]} id="link-modal" show on_cancel={JS.patch(~p"/links")}>
|
||||||
|
<.live_component
|
||||||
|
module={LinkShortenerWeb.LinkLive.FormComponent}
|
||||||
|
id={@link.id || :new}
|
||||||
|
title={@page_title}
|
||||||
|
action={@live_action}
|
||||||
|
link={@link}
|
||||||
|
current_user={@current_user}
|
||||||
|
is_checked={@is_random_shorten_by_default}
|
||||||
|
patch={~p"/links"}
|
||||||
|
/>
|
||||||
|
</.modal>
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
defmodule LinkShortenerWeb.LinkLive.Show do
|
||||||
|
use LinkShortenerWeb, :live_view
|
||||||
|
|
||||||
|
alias LinkShortener.Links
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def mount(_params, _session, socket) do
|
||||||
|
{:ok, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_params(%{"id" => id}, _, socket) do
|
||||||
|
{:noreply,
|
||||||
|
socket
|
||||||
|
|> assign(:page_title, page_title(socket.assigns.live_action))
|
||||||
|
|> assign(:link, Links.get_one!(id))}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp page_title(:show), do: "Show Link"
|
||||||
|
defp page_title(:edit), do: "Edit Link"
|
||||||
|
end
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<.header>
|
||||||
|
Link <%= @link.id %>
|
||||||
|
<:subtitle>This is a link record.</:subtitle>
|
||||||
|
<:actions>
|
||||||
|
<.link patch={~p"/links/#{@link}/show/edit"} phx-click={JS.push_focus()}>
|
||||||
|
<.button>Edit link</.button>
|
||||||
|
</.link>
|
||||||
|
</:actions>
|
||||||
|
</.header>
|
||||||
|
|
||||||
|
<.list>
|
||||||
|
<:item title="Name"><%= @link.name %></:item>
|
||||||
|
<:item title="Url"><%= @link.url %></:item>
|
||||||
|
<:item title="Shorten"><%= @link.shorten %></:item>
|
||||||
|
</.list>
|
||||||
|
|
||||||
|
<.back navigate={~p"/links"}>Back to links</.back>
|
||||||
|
|
||||||
|
<.modal :if={@live_action == :edit} id="link-modal" show on_cancel={JS.patch(~p"/links/#{@link}")}>
|
||||||
|
<.live_component
|
||||||
|
module={LinkShortenerWeb.LinkLive.FormComponent}
|
||||||
|
id={@link.id}
|
||||||
|
title={@page_title}
|
||||||
|
action={@live_action}
|
||||||
|
link={@link}
|
||||||
|
current_user={@current_user}
|
||||||
|
patch={~p"/links/#{@link}"}
|
||||||
|
/>
|
||||||
|
</.modal>
|
||||||
@@ -87,6 +87,13 @@ defmodule LinkShortenerWeb.Router do
|
|||||||
on_mount: [{LinkShortenerWeb.UserAuth, :ensure_authenticated}] do
|
on_mount: [{LinkShortenerWeb.UserAuth, :ensure_authenticated}] do
|
||||||
live "/users/settings", UserSettingsLive, :edit
|
live "/users/settings", UserSettingsLive, :edit
|
||||||
live "/users/settings/confirm_email/:token", UserSettingsLive, :confirm_email
|
live "/users/settings/confirm_email/:token", UserSettingsLive, :confirm_email
|
||||||
|
|
||||||
|
live "/links", LinkLive.Index, :index
|
||||||
|
live "/links/new", LinkLive.Index, :new
|
||||||
|
live "/links/:id/edit", LinkLive.Index, :edit
|
||||||
|
|
||||||
|
live "/links/:id", LinkLive.Show, :show
|
||||||
|
live "/links/:id/show/edit", LinkLive.Show, :edit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ defmodule LinkShortener.MixProject do
|
|||||||
{:guardian_db, "~> 3.0"},
|
{:guardian_db, "~> 3.0"},
|
||||||
{:poison, "~> 5.0"},
|
{:poison, "~> 5.0"},
|
||||||
{:ex_machina, "~> 2.8.0", only: :test},
|
{:ex_machina, "~> 2.8.0", only: :test},
|
||||||
|
{:wallaby, "~> 0.30", runtime: false, only: :test},
|
||||||
|
{:flop, "~> 0.26.1"},
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"bandit": {:hex, :bandit, "1.5.7", "6856b1e1df4f2b0cb3df1377eab7891bec2da6a7fd69dc78594ad3e152363a50", [:mix], [{:hpax, "~> 1.0.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f2dd92ae87d2cbea2fa9aa1652db157b6cba6c405cb44d4f6dd87abba41371cd"},
|
"bandit": {:hex, :bandit, "1.5.7", "6856b1e1df4f2b0cb3df1377eab7891bec2da6a7fd69dc78594ad3e152363a50", [:mix], [{:hpax, "~> 1.0.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "f2dd92ae87d2cbea2fa9aa1652db157b6cba6c405cb44d4f6dd87abba41371cd"},
|
||||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.1.0", "0b110a9a6c619b19a7f73fa3004aa11d6e719a67e672d1633dc36b6b2290a0f7", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2ad2acb5a8bc049e8d5aa267802631912bb80d5f4110a178ae7999e69dca1bf7"},
|
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.1.0", "0b110a9a6c619b19a7f73fa3004aa11d6e719a67e672d1633dc36b6b2290a0f7", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2ad2acb5a8bc049e8d5aa267802631912bb80d5f4110a178ae7999e69dca1bf7"},
|
||||||
"castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"},
|
"castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"},
|
||||||
|
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
|
||||||
"comeonin": {:hex, :comeonin, "5.4.0", "246a56ca3f41d404380fc6465650ddaa532c7f98be4bda1b4656b3a37cc13abe", [:mix], [], "hexpm", "796393a9e50d01999d56b7b8420ab0481a7538d0caf80919da493b4a6e51faf1"},
|
"comeonin": {:hex, :comeonin, "5.4.0", "246a56ca3f41d404380fc6465650ddaa532c7f98be4bda1b4656b3a37cc13abe", [:mix], [], "hexpm", "796393a9e50d01999d56b7b8420ab0481a7538d0caf80919da493b4a6e51faf1"},
|
||||||
"db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
|
"db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"},
|
||||||
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
|
"decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"},
|
||||||
@@ -15,17 +16,24 @@
|
|||||||
"file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},
|
"file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},
|
||||||
"finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
|
"finch": {:hex, :finch, "0.18.0", "944ac7d34d0bd2ac8998f79f7a811b21d87d911e77a786bc5810adb75632ada4", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "69f5045b042e531e53edc2574f15e25e735b522c37e2ddb766e15b979e03aa65"},
|
||||||
"floki": {:hex, :floki, "0.36.2", "a7da0193538c93f937714a6704369711998a51a6164a222d710ebd54020aa7a3", [:mix], [], "hexpm", "a8766c0bc92f074e5cb36c4f9961982eda84c5d2b8e979ca67f5c268ec8ed580"},
|
"floki": {:hex, :floki, "0.36.2", "a7da0193538c93f937714a6704369711998a51a6164a222d710ebd54020aa7a3", [:mix], [], "hexpm", "a8766c0bc92f074e5cb36c4f9961982eda84c5d2b8e979ca67f5c268ec8ed580"},
|
||||||
|
"flop": {:hex, :flop, "0.26.1", "f0e9c6895cf876f667e9ff1c0398e53df87087fcd82d9cea8989332b9c0e1358", [:mix], [{:ecto, "~> 3.11", [hex: :ecto, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}], "hexpm", "5fcab8a1ee78111159fc4752dc9823862343b6d6bd527ff947ec1e1c27018485"},
|
||||||
"gettext": {:hex, :gettext, "0.26.1", "38e14ea5dcf962d1fc9f361b63ea07c0ce715a8ef1f9e82d3dfb8e67e0416715", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "01ce56f188b9dc28780a52783d6529ad2bc7124f9744e571e1ee4ea88bf08734"},
|
"gettext": {:hex, :gettext, "0.26.1", "38e14ea5dcf962d1fc9f361b63ea07c0ce715a8ef1f9e82d3dfb8e67e0416715", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "01ce56f188b9dc28780a52783d6529ad2bc7124f9744e571e1ee4ea88bf08734"},
|
||||||
"guardian": {:hex, :guardian, "2.3.2", "78003504b987f2b189d76ccf9496ceaa6a454bb2763627702233f31eb7212881", [:mix], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "b189ff38cd46a22a8a824866a6867ca8722942347f13c33f7d23126af8821b52"},
|
"guardian": {:hex, :guardian, "2.3.2", "78003504b987f2b189d76ccf9496ceaa6a454bb2763627702233f31eb7212881", [:mix], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "b189ff38cd46a22a8a824866a6867ca8722942347f13c33f7d23126af8821b52"},
|
||||||
"guardian_db": {:hex, :guardian_db, "3.0.0", "c42902e3f1af1ba1e2d0c10913b926a1421f3a7e38eb4fc382b715c17489abdb", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:guardian, "~> 1.0 or ~> 2.0", [hex: :guardian, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "9c2ec4278efa34f9f1cc6ba795e552d41fdc7ffba5319d67eeb533b89392d183"},
|
"guardian_db": {:hex, :guardian_db, "3.0.0", "c42902e3f1af1ba1e2d0c10913b926a1421f3a7e38eb4fc382b715c17489abdb", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.1", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:guardian, "~> 1.0 or ~> 2.0", [hex: :guardian, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "9c2ec4278efa34f9f1cc6ba795e552d41fdc7ffba5319d67eeb533b89392d183"},
|
||||||
|
"hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~>2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"},
|
||||||
"heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized"]},
|
"heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized"]},
|
||||||
"hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"},
|
"hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"},
|
||||||
|
"httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"},
|
||||||
|
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||||
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
||||||
"jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"},
|
"jose": {:hex, :jose, "1.11.10", "a903f5227417bd2a08c8a00a0cbcc458118be84480955e8d251297a425723f83", [:mix, :rebar3], [], "hexpm", "0d6cd36ff8ba174db29148fc112b5842186b68a90ce9fc2b3ec3afe76593e614"},
|
||||||
|
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||||
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
|
"mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"},
|
||||||
|
"mimerl": {:hex, :mimerl, "1.3.0", "d0cd9fc04b9061f82490f6581e0128379830e78535e017f7780f37fea7545726", [:rebar3], [], "hexpm", "a1e15a50d1887217de95f0b9b0793e32853f7c258a5cd227650889b38839fe9d"},
|
||||||
"mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"},
|
"mint": {:hex, :mint, "1.6.2", "af6d97a4051eee4f05b5500671d47c3a67dac7386045d87a904126fd4bbcea2e", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5ee441dffc1892f1ae59127f74afe8fd82fda6587794278d924e4d90ea3d63f9"},
|
||||||
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
|
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
|
||||||
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
|
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
|
||||||
|
"parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"},
|
||||||
"phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"},
|
"phoenix": {:hex, :phoenix, "1.7.14", "a7d0b3f1bc95987044ddada111e77bd7f75646a08518942c72a8440278ae7825", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c7859bc56cc5dfef19ecfc240775dae358cbaa530231118a9e014df392ace61a"},
|
||||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.6.2", "3b83b24ab5a2eb071a20372f740d7118767c272db386831b2e77638c4dcc606d", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "3f94d025f59de86be00f5f8c5dd7b5965a3298458d21ab1c328488be3b5fcd59"},
|
"phoenix_ecto": {:hex, :phoenix_ecto, "4.6.2", "3b83b24ab5a2eb071a20372f740d7118767c272db386831b2e77638c4dcc606d", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "3f94d025f59de86be00f5f8c5dd7b5965a3298458d21ab1c328488be3b5fcd59"},
|
||||||
"phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"},
|
"phoenix_html": {:hex, :phoenix_html, "4.1.1", "4c064fd3873d12ebb1388425a8f2a19348cef56e7289e1998e2d2fa758aa982e", [:mix], [], "hexpm", "f2f2df5a72bc9a2f510b21497fd7d2b86d932ec0598f0210fed4114adc546c6f"},
|
||||||
@@ -38,12 +46,17 @@
|
|||||||
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
|
"plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
|
||||||
"poison": {:hex, :poison, "5.0.0", "d2b54589ab4157bbb82ec2050757779bfed724463a544b6e20d79855a9e43b24", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "11dc6117c501b80c62a7594f941d043982a1bd05a1184280c0d9166eb4d8d3fc"},
|
"poison": {:hex, :poison, "5.0.0", "d2b54589ab4157bbb82ec2050757779bfed724463a544b6e20d79855a9e43b24", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "11dc6117c501b80c62a7594f941d043982a1bd05a1184280c0d9166eb4d8d3fc"},
|
||||||
"postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"},
|
"postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"},
|
||||||
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
|
||||||
"swoosh": {:hex, :swoosh, "1.16.12", "cbb24ad512f2f7f24c7a469661c188a00a8c2cd64e0ab54acd1520f132092dfd", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0e262df1ae510d59eeaaa3db42189a2aa1b3746f73771eb2616fc3f7ee63cc20"},
|
"swoosh": {:hex, :swoosh, "1.16.12", "cbb24ad512f2f7f24c7a469661c188a00a8c2cd64e0ab54acd1520f132092dfd", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0e262df1ae510d59eeaaa3db42189a2aa1b3746f73771eb2616fc3f7ee63cc20"},
|
||||||
"tailwind": {:hex, :tailwind, "0.2.3", "277f08145d407de49650d0a4685dc062174bdd1ae7731c5f1da86163a24dfcdb", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "8e45e7a34a676a7747d04f7913a96c770c85e6be810a1d7f91e713d3a3655b5d"},
|
"tailwind": {:hex, :tailwind, "0.2.3", "277f08145d407de49650d0a4685dc062174bdd1ae7731c5f1da86163a24dfcdb", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "8e45e7a34a676a7747d04f7913a96c770c85e6be810a1d7f91e713d3a3655b5d"},
|
||||||
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
|
"telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"},
|
||||||
"telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"},
|
"telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"},
|
||||||
"telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"},
|
"telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"},
|
||||||
|
"tesla": {:hex, :tesla, "1.12.1", "fe2bf4250868ee72e5d8b8dfa408d13a00747c41b7237b6aa3b9a24057346681", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "2391efc6243d37ead43afd0327b520314c7b38232091d4a440c1212626fdd6e7"},
|
||||||
"thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"},
|
"thousand_island": {:hex, :thousand_island, "1.3.5", "6022b6338f1635b3d32406ff98d68b843ba73b3aa95cfc27154223244f3a6ca5", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2be6954916fdfe4756af3239fb6b6d75d0b8063b5df03ba76fd8a4c87849e180"},
|
||||||
|
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
|
||||||
|
"wallaby": {:hex, :wallaby, "0.30.9", "51d60682092c3c428c63b656b818e2258202b9f9a31ec37230659647ae20325b", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}, {:httpoison, "~> 0.12 or ~> 1.0 or ~> 2.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:phoenix_ecto, ">= 3.0.0", [hex: :phoenix_ecto, repo: "hexpm", optional: true]}, {:web_driver_client, "~> 0.2.0", [hex: :web_driver_client, repo: "hexpm", optional: false]}], "hexpm", "62e3ccb89068b231b50ed046219022020516d44f443eebef93a19db4be95b808"},
|
||||||
|
"web_driver_client": {:hex, :web_driver_client, "0.2.0", "63b76cd9eb3b0716ec5467a0f8bead73d3d9612e63f7560d21357f03ad86e31a", [:mix], [{:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:tesla, "~> 1.3", [hex: :tesla, repo: "hexpm", optional: false]}], "hexpm", "83cc6092bc3e74926d1c8455f0ce927d5d1d36707b74d9a65e38c084aab0350f"},
|
||||||
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
|
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
|
||||||
"websock_adapter": {:hex, :websock_adapter, "0.5.7", "65fa74042530064ef0570b75b43f5c49bb8b235d6515671b3d250022cb8a1f9e", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d0f478ee64deddfec64b800673fd6e0c8888b079d9f3444dd96d2a98383bdbd1"},
|
"websock_adapter": {:hex, :websock_adapter, "0.5.7", "65fa74042530064ef0570b75b43f5c49bb8b235d6515671b3d250022cb8a1f9e", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d0f478ee64deddfec64b800673fd6e0c8888b079d9f3444dd96d2a98383bdbd1"},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
defmodule LinkShortener.Generators.LinkWithRandomShortenTest do
|
defmodule LinkShortener.Generators.LinkWithRandomShortenTest do
|
||||||
use ExUnit.Case, async: true
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
alias LinkShortener.Generators.LinkWithRandomShorten
|
alias LinkShortener.Generators.LinkWithRandomShorten
|
||||||
|
|
||||||
@name "Some name"
|
@name "Some name"
|
||||||
@attrs %{
|
@attrs %{
|
||||||
name: @name
|
name: @name
|
||||||
}
|
}
|
||||||
|
|
||||||
test "generate/1 returns random safe string with 10 as length" do
|
test "generate/1 returns random safe string with 10 as length" do
|
||||||
assert %{
|
assert %{
|
||||||
name: @name,
|
name: @name,
|
||||||
shorten: shorten
|
shorten: shorten
|
||||||
} = LinkWithRandomShorten.generate_one(@attrs)
|
} = LinkWithRandomShorten.generate_one(@attrs)
|
||||||
|
|
||||||
assert String.length(shorten) == 10
|
assert String.length(shorten) == 10
|
||||||
end
|
end
|
||||||
@@ -21,22 +21,32 @@ defmodule LinkShortener.Generators.LinkWithRandomShortenTest do
|
|||||||
expected_length = 5
|
expected_length = 5
|
||||||
|
|
||||||
assert %{
|
assert %{
|
||||||
name: @name,
|
name: @name,
|
||||||
shorten: shorten
|
shorten: shorten
|
||||||
} = LinkWithRandomShorten.generate_one(@attrs, expected_length)
|
} =
|
||||||
|
LinkWithRandomShorten.generate_one(@attrs,
|
||||||
|
is_atom_based: true,
|
||||||
|
length: expected_length
|
||||||
|
)
|
||||||
|
|
||||||
assert String.length(shorten) == expected_length
|
assert String.length(shorten) == expected_length
|
||||||
end
|
end
|
||||||
|
|
||||||
test "generate/3 returns random safe string using a lambda function" do
|
test "generate/3 returns random safe string using a lambda function" do
|
||||||
random_generator = fn _ -> "random_shorten" end
|
random_generator = fn _ -> "random_shorten" end
|
||||||
expected_shorten = random_generator.(14)
|
expected_shorten = random_generator.(14)
|
||||||
expected_length = expected_shorten |> String.length()
|
expected_length = expected_shorten |> String.length()
|
||||||
|
|
||||||
assert %{
|
assert %{
|
||||||
name: @name,
|
name: @name,
|
||||||
shorten: shorten
|
shorten: shorten
|
||||||
} = LinkWithRandomShorten.generate_one(@attrs, expected_length, random_generator)
|
} =
|
||||||
|
LinkWithRandomShorten.generate_one(
|
||||||
|
@attrs,
|
||||||
|
is_atom_based: true,
|
||||||
|
length: expected_length,
|
||||||
|
generator: random_generator
|
||||||
|
)
|
||||||
|
|
||||||
assert String.length(shorten) == expected_length
|
assert String.length(shorten) == expected_length
|
||||||
assert shorten == expected_shorten
|
assert shorten == expected_shorten
|
||||||
|
|||||||
@@ -4,14 +4,13 @@ defmodule LinkShortener.Generators.SafeStringTest do
|
|||||||
alias LinkShortener.Generators.SafeString
|
alias LinkShortener.Generators.SafeString
|
||||||
|
|
||||||
@lengths [1, 2, 5, 10]
|
@lengths [1, 2, 5, 10]
|
||||||
|
|
||||||
test "generate/1 returns random safe string with same length" do
|
test "generate/1 returns random safe string with same length" do
|
||||||
for expected_length <- @lengths do
|
for expected_length <- @lengths do
|
||||||
length = expected_length
|
assert ^expected_length =
|
||||||
|> SafeString.generate()
|
expected_length
|
||||||
|> String.length()
|
|> SafeString.generate()
|
||||||
|
|> String.length()
|
||||||
assert length = expected_length
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ defmodule LinkShortener.LinksTest do
|
|||||||
test "create_one/2 with valid data creates a link", %{user: user} do
|
test "create_one/2 with valid data creates a link", %{user: user} do
|
||||||
assert {:ok, %Link{} = link} =
|
assert {:ok, %Link{} = link} =
|
||||||
with_user(@create_generated_attrs, user)
|
with_user(@create_generated_attrs, user)
|
||||||
|> Links.create_one(5)
|
|> Links.create_one(length: 5)
|
||||||
|
|
||||||
assert link.name == "some link name"
|
assert link.name == "some link name"
|
||||||
assert link.url == "https://gitlab.com/KKlochko/link_shortener"
|
assert link.url == "https://gitlab.com/KKlochko/link_shortener"
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
defmodule LinkShortenerWeb.Features.LinkLiveTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
use Wallaby.Feature
|
||||||
|
|
||||||
|
import LinkShortener.LinksFixtures
|
||||||
|
import LinkShortener.AccountsFixtures
|
||||||
|
|
||||||
|
alias LinkShortener.Factories.UserFactory
|
||||||
|
alias LinkShortener.Factories.LinkFactory
|
||||||
|
|
||||||
|
alias LinkShortener.Links
|
||||||
|
alias LinkShortener.Links.Link
|
||||||
|
|
||||||
|
@create_attrs %{name: "some name", shorten: "some shorten", url: "some url"}
|
||||||
|
@update_attrs %{name: "some updated name", shorten: "some updated shorten", url: "some updated url"}
|
||||||
|
@invalid_attrs %{name: nil, shorten: nil, url: nil}
|
||||||
|
|
||||||
|
setup %{session: session} do
|
||||||
|
user_attrs = UserFactory.user_attrs_factory()
|
||||||
|
user = user_fixture(user_attrs)
|
||||||
|
link = LinkFactory.create_link(%{user_id: user.id})
|
||||||
|
|
||||||
|
%{session: log_in_user(session, user_attrs),
|
||||||
|
user: user,
|
||||||
|
user_attrs: user_attrs,
|
||||||
|
link: link}
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Index" do
|
||||||
|
test "saves new link without a random shorten", %{session: session} do
|
||||||
|
new_link = LinkFactory.link_attrs_factory()
|
||||||
|
|
||||||
|
session
|
||||||
|
|> visit("/links")
|
||||||
|
|> click(Query.button("New Link"))
|
||||||
|
|> click(Query.checkbox("Random shorten"))
|
||||||
|
|> fill_in(Query.text_field("Name"), with: new_link.name)
|
||||||
|
|> fill_in(Query.text_field("Url"), with: new_link.url)
|
||||||
|
|> fill_in(Query.text_field("Shorten"), with: new_link.shorten)
|
||||||
|
|> click(Query.button("Save Link"))
|
||||||
|
|> assert_has(Query.xpath("//*[@id='flash-info']", text: "Link created successfully"))
|
||||||
|
|
||||||
|
assert Links.get_one_by_shorten(new_link.shorten)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def log_in_user(session, user) do
|
||||||
|
session
|
||||||
|
|> visit("/users/log_in/")
|
||||||
|
|> fill_in(Query.text_field("Email"), with: user.email)
|
||||||
|
|> fill_in(Query.text_field("Password"), with: user.password)
|
||||||
|
|> click(Query.button("Log in"))
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
defmodule LinkShortenerWeb.LinkLiveTest do
|
||||||
|
use LinkShortenerWeb.ConnCase
|
||||||
|
|
||||||
|
import Phoenix.LiveViewTest
|
||||||
|
import LinkShortener.LinksFixtures
|
||||||
|
import LinkShortener.AccountsFixtures
|
||||||
|
|
||||||
|
alias LinkShortener.Factories.LinkFactory
|
||||||
|
|
||||||
|
@create_attrs %{name: "some name", shorten: "some shorten", url: "some url"}
|
||||||
|
@update_attrs %{name: "some updated name", shorten: "some updated shorten", url: "some updated url"}
|
||||||
|
@invalid_attrs %{name: nil, shorten: nil, url: nil}
|
||||||
|
|
||||||
|
setup %{conn: conn} do
|
||||||
|
user = user_fixture()
|
||||||
|
link = LinkFactory.create_link(%{user_id: user.id})
|
||||||
|
|
||||||
|
%{conn: log_in_user(conn, user),
|
||||||
|
user: user,
|
||||||
|
link: link}
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Index" do
|
||||||
|
test "lists all links", %{conn: conn, link: link} do
|
||||||
|
{:ok, _index_live, html} = live(conn, ~p"/links")
|
||||||
|
|
||||||
|
assert html =~ "Listing Links"
|
||||||
|
assert html =~ link.name
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag :skip
|
||||||
|
test "saves new link", %{conn: conn} do
|
||||||
|
{:ok, index_live, _html} = live(conn, ~p"/links")
|
||||||
|
|
||||||
|
assert index_live |> element("a", "New Link") |> render_click() =~
|
||||||
|
"New Link"
|
||||||
|
|
||||||
|
assert_patch(index_live, ~p"/links/new")
|
||||||
|
|
||||||
|
assert index_live
|
||||||
|
|> element("#random-toggle")
|
||||||
|
|> render_click()
|
||||||
|
|
||||||
|
assert index_live
|
||||||
|
|> form("#link-form", link: @invalid_attrs)
|
||||||
|
|> render_change() =~ "can't be blank"
|
||||||
|
|
||||||
|
assert index_live
|
||||||
|
|> form("#link-form", link: @create_attrs)
|
||||||
|
|> render_submit()
|
||||||
|
|
||||||
|
assert_patch(index_live, ~p"/links")
|
||||||
|
|
||||||
|
html = render(index_live)
|
||||||
|
assert html =~ "Link created successfully"
|
||||||
|
assert html =~ "some name"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "updates link in listing", %{conn: conn, link: link} do
|
||||||
|
{:ok, index_live, _html} = live(conn, ~p"/links")
|
||||||
|
|
||||||
|
assert index_live |> element("#links-#{link.id} a", "Edit") |> render_click() =~
|
||||||
|
"Edit Link"
|
||||||
|
|
||||||
|
assert_patch(index_live, ~p"/links/#{link}/edit")
|
||||||
|
|
||||||
|
assert index_live
|
||||||
|
|> form("#link-form", link: @invalid_attrs)
|
||||||
|
|> render_change() =~ "can't be blank"
|
||||||
|
|
||||||
|
assert index_live
|
||||||
|
|> form("#link-form", link: @update_attrs)
|
||||||
|
|> render_submit()
|
||||||
|
|
||||||
|
assert_patch(index_live, ~p"/links")
|
||||||
|
|
||||||
|
html = render(index_live)
|
||||||
|
assert html =~ "Link updated successfully"
|
||||||
|
assert html =~ "some updated name"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "deletes link in listing", %{conn: conn, link: link} do
|
||||||
|
{:ok, index_live, _html} = live(conn, ~p"/links")
|
||||||
|
|
||||||
|
assert index_live |> element("#links-#{link.id} a", "Delete") |> render_click()
|
||||||
|
refute has_element?(index_live, "#links-#{link.id}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "Show" do
|
||||||
|
test "displays link", %{conn: conn, link: link} do
|
||||||
|
{:ok, _show_live, html} = live(conn, ~p"/links/#{link}")
|
||||||
|
|
||||||
|
assert html =~ "Show Link"
|
||||||
|
assert html =~ link.name
|
||||||
|
end
|
||||||
|
|
||||||
|
test "updates link within modal", %{conn: conn, link: link} do
|
||||||
|
{:ok, show_live, _html} = live(conn, ~p"/links/#{link}")
|
||||||
|
|
||||||
|
assert show_live |> element("a", "Edit") |> render_click() =~
|
||||||
|
"Edit Link"
|
||||||
|
|
||||||
|
assert_patch(show_live, ~p"/links/#{link}/show/edit")
|
||||||
|
|
||||||
|
assert show_live
|
||||||
|
|> form("#link-form", link: @invalid_attrs)
|
||||||
|
|> render_change() =~ "can't be blank"
|
||||||
|
|
||||||
|
assert show_live
|
||||||
|
|> form("#link-form", link: @update_attrs)
|
||||||
|
|> render_submit()
|
||||||
|
|
||||||
|
assert_patch(show_live, ~p"/links/#{link}")
|
||||||
|
|
||||||
|
html = render(show_live)
|
||||||
|
assert html =~ "Link updated successfully"
|
||||||
|
assert html =~ "some updated name"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,2 +1,5 @@
|
|||||||
ExUnit.start()
|
ExUnit.start()
|
||||||
Ecto.Adapters.SQL.Sandbox.mode(LinkShortener.Repo, :manual)
|
Ecto.Adapters.SQL.Sandbox.mode(LinkShortener.Repo, :manual)
|
||||||
|
|
||||||
|
{:ok, _} = Application.ensure_all_started(:wallaby)
|
||||||
|
Application.put_env(:wallaby, :base_url, LinkShortenerWeb.Endpoint.url)
|
||||||
|
|||||||
Reference in New Issue
Block a user