9 | <%= f = form_for :heading, "#", [phx_submit: :set_title, "phx-target": "##{@id}"] %>
10 | <%= label f, :title %>
11 | <%= text_input f, :title %>
12 |
15 |
16 | """
17 | end
18 |
19 | def mount(socket) do
20 | {:ok, socket}
21 | end
22 |
23 | def update(%{title: title, id: id}, socket) do
24 | {:ok,
25 | assign(socket,
26 | title: title,
27 | id: id
28 | )}
29 | end
30 |
31 | def handle_event(
32 | "set_title",
33 | %{"heading" => %{"title" => updated_title}},
34 | socket
35 | ) do
36 | send(
37 | self(),
38 | {__MODULE__, :updated_title, %{title: updated_title}}
39 | )
40 |
41 | {:noreply, socket}
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/lib/demo_web/live/example_live/stateful_send_self_component_live_view.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.StatefulSendSelfComponentLiveView do
2 | use DemoWeb, :live_view
3 |
4 | def render(assigns) do
5 | ~L"""
6 |
7 | <%= live_component(
8 | @socket,
9 | DemoWeb.StatefulSendSelfComponent,
10 | id: "stateful-send-self-component",
11 | title: @title
12 | )
13 | %>
14 |
15 | """
16 | end
17 |
18 | def mount(_params, _session, socket) do
19 | {:ok,
20 | assign(socket,
21 | title: "Initial Title"
22 | )}
23 | end
24 |
25 | def handle_params(_params, _uri, socket) do
26 | {:noreply, socket}
27 | end
28 |
29 | def handle_info(
30 | {DemoWeb.StatefulSendSelfComponent, :updated_title, %{title: updated_title}},
31 | socket
32 | ) do
33 | {:noreply, assign(socket, title: updated_title)}
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/lib/demo_web/live/example_live/stateless_component.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.StatelessComponent do
2 | use Phoenix.LiveComponent
3 | use Phoenix.HTML
4 |
5 | def render(assigns) do
6 | ~L"""
7 |
9 | <%= f = form_for :heading, "#", [phx_submit: :set_title] %>
10 | <%= label f, :title %>
11 | <%= text_input f, :title %>
12 |
13 | <%= submit "Set", phx_disable_with: "Setting..." %>
14 |
15 |
16 | """
17 | end
18 |
19 | def mount(socket) do
20 | {:ok, socket}
21 | end
22 |
23 | def update(%{title: title}, socket) do
24 | {:ok, assign(socket, title: title)}
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/lib/demo_web/live/example_live/stateless_component_live_view.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.StatelessComponentLiveView do
2 | use DemoWeb, :live_view
3 |
4 | def render(assigns) do
5 | ~L"""
6 |
7 | <%= live_component(
8 | @socket,
9 | DemoWeb.StatelessComponent,
10 | title: @title
11 | )
12 | %>
13 |
14 | """
15 | end
16 |
17 | def mount(_params, _session, socket) do
18 | {:ok,
19 | assign(socket,
20 | title: "Initial Title"
21 | )}
22 | end
23 |
24 | def handle_event(
25 | "set_title",
26 | %{"heading" => %{"title" => updated_title}},
27 | socket
28 | ) do
29 | {:noreply, assign(socket, title: updated_title)}
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/lib/demo_web/live/example_live/static_title_component.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.StaticTitleComponent do
2 | use Phoenix.LiveComponent
3 |
4 | def render(assigns) do
5 | ~L"""
6 |
Title
7 | """
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/lib/demo_web/live/example_live/static_title_live_view.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.StaticTitleLiveView do
2 | use Phoenix.LiveView
3 |
4 | def render(assigns) do
5 | ~L"""
6 |
7 | <%= live_component(
8 | @socket,
9 | DemoWeb.StaticTitleComponent
10 | )
11 | %>
12 |
13 | """
14 | end
15 |
16 | def mount(_params, _session, socket) do
17 | {:ok, socket}
18 | end
19 |
20 | def handle_params(_params, _uri, socket) do
21 | {:noreply, socket}
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/lib/demo_web/live/page_live.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.PageLive do
2 | use DemoWeb, :live_view
3 |
4 | @impl true
5 | def mount(_params, _session, socket) do
6 | {:ok, assign(socket, query: "", results: %{})}
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/lib/demo_web/live/page_live.html.leex:
--------------------------------------------------------------------------------
1 |
2 | <%= gettext "Welcome to %{name}!", name: "Phoenix LiveView" %>
3 |
4 |
5 |
6 | LiveView LiveComponent Examples
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/lib/demo_web/router.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.Router do
2 | use DemoWeb, :router
3 |
4 | pipeline :browser do
5 | plug :accepts, ["html"]
6 | plug :fetch_session
7 | plug :fetch_live_flash
8 | plug :put_root_layout, {DemoWeb.LayoutView, :root}
9 | plug :protect_from_forgery
10 | plug :put_secure_browser_headers
11 | end
12 |
13 | pipeline :api do
14 | plug :accepts, ["json"]
15 | end
16 |
17 | scope "/", DemoWeb do
18 | pipe_through :browser
19 |
20 | live "/", PageLive, :index
21 |
22 | live "/counter", CounterLive, :show
23 |
24 | live "/counter/confirm-boom", CounterLive, :confirm_boom
25 |
26 | live "/examples", LiveComponentExamples
27 |
28 | live "/examples/static-title", StaticTitleLiveView
29 |
30 | live "/examples/assigns-title", AssignsTitleLiveView
31 |
32 | live "/examples/stateless-component", StatelessComponentLiveView
33 |
34 | live "/examples/stateful-component", StatefulComponentLiveView
35 |
36 | live "/examples/stateful-send-self-component", StatefulSendSelfComponentLiveView
37 |
38 | live "/examples/stateful-preload-component", StatefulPreloadComponentLiveView
39 |
40 | live "/examples/component-blocks", ComponentBlocksLiveView
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/lib/demo_web/telemetry.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.Telemetry do
2 | use Supervisor
3 | import Telemetry.Metrics
4 |
5 | def start_link(arg) do
6 | Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
7 | end
8 |
9 | @impl true
10 | def init(_arg) do
11 | children = [
12 | # Telemetry poller will execute the given period measurements
13 | # every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics
14 | {:telemetry_poller, measurements: periodic_measurements(), period: 10_000}
15 | # Add reporters as children of your supervision tree.
16 | # {Telemetry.Metrics.ConsoleReporter, metrics: metrics()}
17 | ]
18 |
19 | Supervisor.init(children, strategy: :one_for_one)
20 | end
21 |
22 | def metrics do
23 | [
24 | # Phoenix Metrics
25 | summary("phoenix.endpoint.stop.duration",
26 | unit: {:native, :millisecond}
27 | ),
28 | summary("phoenix.router_dispatch.stop.duration",
29 | tags: [:route],
30 | unit: {:native, :millisecond}
31 | ),
32 |
33 | # VM Metrics
34 | summary("vm.memory.total", unit: {:byte, :kilobyte}),
35 | summary("vm.total_run_queue_lengths.total"),
36 | summary("vm.total_run_queue_lengths.cpu"),
37 | summary("vm.total_run_queue_lengths.io")
38 | ]
39 | end
40 |
41 | defp periodic_measurements do
42 | [
43 | # A module, function and arguments to be invoked periodically.
44 | # This function must call :telemetry.execute/3 and a metric must be added above.
45 | # {DemoWeb, :count_users, []}
46 | ]
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/lib/demo_web/templates/layout/app.html.eex:
--------------------------------------------------------------------------------
1 |
2 | <%= get_flash(@conn, :info) %>
3 | <%= get_flash(@conn, :error) %>
4 | <%= @inner_content %>
5 |
6 |
--------------------------------------------------------------------------------
/lib/demo_web/templates/layout/live.html.leex:
--------------------------------------------------------------------------------
1 |
2 | <%= live_flash(@flash, :info) %>
5 |
6 | <%= live_flash(@flash, :error) %>
9 |
10 | <%= @inner_content %>
11 |
12 |
--------------------------------------------------------------------------------
/lib/demo_web/templates/layout/root.html.leex:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | <%= csrf_meta_tag() %>
8 | <%= live_title_tag assigns[:page_title] || "Demo", suffix: " · Phoenix Framework" %>
9 |
"/>
10 |
11 |
12 |
13 |
28 | <%= @inner_content %>
29 |
30 |
31 |
--------------------------------------------------------------------------------
/lib/demo_web/templates/page/index.html.eex:
--------------------------------------------------------------------------------
1 |
2 | <%= gettext "Welcome to %{name}!", name: "Phoenix LiveView" %>
3 |
4 |
5 |
6 | LiveView LiveComponent Examples
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/lib/demo_web/templates/page/keyboard.html.leex:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - <%= @elapsed_seconds %>s
5 | - WPM
6 | - <%= @wpm %>
7 | - Accuracy:
8 | - <%= @accuracy %>%
9 |
10 |
11 |
12 | <%= for char <- @chars do %>
13 |
<%= if char.dim, do: "dim " %><%= if char.mark, do: "mark " %>">
14 | <%= char.text %>
15 |
16 |
">
17 | <% end %>
18 |
19 |
20 |
21 |
22 |
23 |
24 | -
25 |
29 |
30 | -
31 |
35 |
36 | -
37 |
41 |
42 | -
43 |
47 |
48 | -
49 |
53 |
54 | -
55 |
59 |
60 | -
61 |
65 |
66 | -
67 |
71 |
72 | -
73 |
77 |
78 | -
79 |
83 |
84 | -
85 |
89 |
90 | -
91 |
95 |
96 | -
97 |
101 |
102 | - delete
103 |
104 |
105 |
106 |
107 | - tab
108 | - q
109 | - w
110 | - e
111 | - r
112 | - t
113 | - y
114 | - u
115 | - i
116 | - o
117 | - p
118 | -
119 |
123 |
124 | -
125 |
129 |
130 | -
131 |
135 |
136 |
137 |
138 |
139 | - capslock
140 | - a
141 | - s
142 | - d
143 | - f
_
144 | - g
145 | - h
146 | - j
_
147 | - k
148 | - l
149 | -
150 |
154 |
155 | -
156 |
160 |
161 | -
162 | return
163 |
164 |
165 |
166 |
167 | - shift
168 | - z
169 | - x
170 | - c
171 | - v
172 | - b
173 | - n
174 | - m
175 | -
176 |
180 |
181 | -
182 |
186 |
187 | -
188 |
192 |
193 | -
194 | shift
195 |
196 |
197 |
198 |
199 | - control
200 | - alt
201 | - space
202 | - alt
203 | - control
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |

212 |
213 |
214 |

215 |
216 |
217 |
218 |
219 |
220 |

221 |

222 |

223 |

224 |

225 |

226 |

227 |

228 |

229 |

230 |

231 |

232 |
233 |
--------------------------------------------------------------------------------
/lib/demo_web/templates/page/px.html.leex:
--------------------------------------------------------------------------------
1 |
<%= @px %>px
2 | <%= "
" %>
3 |
--------------------------------------------------------------------------------
/lib/demo_web/views/error_helpers.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.ErrorHelpers do
2 | @moduledoc """
3 | Conveniences for translating and building error messages.
4 | """
5 |
6 | use Phoenix.HTML
7 |
8 | @doc """
9 | Generates tag for inlined form input errors.
10 | """
11 | def error_tag(form, field) do
12 | Enum.map(Keyword.get_values(form.errors, field), fn error ->
13 | content_tag(:span, translate_error(error),
14 | class: "invalid-feedback",
15 | phx_feedback_for: input_id(form, field)
16 | )
17 | end)
18 | end
19 |
20 | @doc """
21 | Translates an error message using gettext.
22 | """
23 | def translate_error({msg, opts}) do
24 | # When using gettext, we typically pass the strings we want
25 | # to translate as a static argument:
26 | #
27 | # # Translate "is invalid" in the "errors" domain
28 | # dgettext("errors", "is invalid")
29 | #
30 | # # Translate the number of files with plural rules
31 | # dngettext("errors", "1 file", "%{count} files", count)
32 | #
33 | # Because the error messages we show in our forms and APIs
34 | # are defined inside Ecto, we need to translate them dynamically.
35 | # This requires us to call the Gettext module passing our gettext
36 | # backend as first argument.
37 | #
38 | # Note we use the "errors" domain, which means translations
39 | # should be written to the errors.po file. The :count option is
40 | # set by Ecto and indicates we should also apply plural rules.
41 | if count = opts[:count] do
42 | Gettext.dngettext(DemoWeb.Gettext, "errors", msg, msg, count, opts)
43 | else
44 | Gettext.dgettext(DemoWeb.Gettext, "errors", msg, opts)
45 | end
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/lib/demo_web/views/error_view.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.ErrorView do
2 | use DemoWeb, :view
3 |
4 | # If you want to customize a particular status code
5 | # for a certain format, you may uncomment below.
6 | # def render("500.html", _assigns) do
7 | # "Internal Server Error"
8 | # end
9 |
10 | # By default, Phoenix returns the status message from
11 | # the template name. For example, "404.html" becomes
12 | # "Not Found".
13 | def template_not_found(template, _assigns) do
14 | Phoenix.Controller.status_message_from_template(template)
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/demo_web/views/layout_view.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.LayoutView do
2 | use DemoWeb, :view
3 | end
4 |
--------------------------------------------------------------------------------
/mix.exs:
--------------------------------------------------------------------------------
1 | defmodule Demo.MixProject do
2 | use Mix.Project
3 |
4 | def project do
5 | [
6 | app: :demo,
7 | version: "0.1.0",
8 | elixir: "~> 1.7",
9 | elixirc_paths: elixirc_paths(Mix.env()),
10 | compilers: [:phoenix, :gettext] ++ Mix.compilers(),
11 | start_permanent: Mix.env() == :prod,
12 | aliases: aliases(),
13 | deps: deps()
14 | ]
15 | end
16 |
17 | # Configuration for the OTP application.
18 | #
19 | # Type `mix help compile.app` for more information.
20 | def application do
21 | [
22 | mod: {Demo.Application, []},
23 | extra_applications: [:logger, :runtime_tools]
24 | ]
25 | end
26 |
27 | # Specifies which paths to compile per environment.
28 | defp elixirc_paths(:test), do: ["lib", "test/support"]
29 | defp elixirc_paths(_), do: ["lib"]
30 |
31 | # Specifies your project dependencies.
32 | #
33 | # Type `mix help deps` for examples and options.
34 | defp deps do
35 | [
36 | {:phoenix, "~> 1.5.3"},
37 | {:phoenix_live_view, "~> 0.14.4"},
38 | {:floki, ">= 0.0.0", only: :test},
39 | {:phoenix_html, "~> 2.11"},
40 | {:phoenix_live_reload, "~> 1.2", only: :dev},
41 | {:phoenix_live_dashboard, "~> 0.2.0"},
42 | {:telemetry_metrics, "~> 0.4"},
43 | {:telemetry_poller, "~> 0.4"},
44 | {:gettext, "~> 0.11"},
45 | {:jason, "~> 1.0"},
46 | {:plug_cowboy, "~> 2.0"}
47 | ]
48 | end
49 |
50 | # Aliases are shortcuts or tasks specific to the current project.
51 | # For example, to install project dependencies and perform other setup tasks, run:
52 | #
53 | # $ mix setup
54 | #
55 | # See the documentation for `Mix` for more info on aliases.
56 | defp aliases do
57 | [
58 | setup: ["deps.get", "cmd npm install --prefix assets"]
59 | ]
60 | end
61 | end
62 |
--------------------------------------------------------------------------------
/mix.lock:
--------------------------------------------------------------------------------
1 | %{
2 | "cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"},
3 | "cowlib": {:hex, :cowlib, "2.9.1", "61a6c7c50cf07fdd24b2f45b89500bb93b6686579b069a89f88cb211e1125c78", [:rebar3], [], "hexpm", "e4175dc240a70d996156160891e1c62238ede1729e45740bdd38064dad476170"},
4 | "file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm", "97a3b6f8d63ef53bd0113070102db2ce05352ecf0d25390eb8d747c2bde98bca"},
5 | "floki": {:hex, :floki, "0.28.0", "0d0795a17189510ee01323e6990f906309e9fc6e8570219135211f1264d78c7f", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "db1549560874ebba5a6367e46c3aec5fedd41f2757ad6efe567efb04b4d4ee55"},
6 | "gettext": {:hex, :gettext, "0.18.1", "89e8499b051c7671fa60782faf24409b5d2306aa71feb43d79648a8bc63d0522", [:mix], [], "hexpm", "e70750c10a5f88cb8dc026fc28fa101529835026dec4a06dba3b614f2a99c7a9"},
7 | "html_entities": {:hex, :html_entities, "0.5.1", "1c9715058b42c35a2ab65edc5b36d0ea66dd083767bef6e3edb57870ef556549", [:mix], [], "hexpm", "30efab070904eb897ff05cd52fa61c1025d7f8ef3a9ca250bc4e6513d16c32de"},
8 | "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b659b8571deedf60f79c5a608e15414085fa141344e2716fbd6988a084b5f993"},
9 | "mime": {:hex, :mime, "1.4.0", "5066f14944b470286146047d2f73518cf5cca82f8e4815cf35d196b58cf07c47", [:mix], [], "hexpm", "75fa42c4228ea9a23f70f123c74ba7cece6a03b1fd474fe13f6a7a85c6ea4ff6"},
10 | "phoenix": {:hex, :phoenix, "1.5.4", "0fca9ce7e960f9498d6315e41fcd0c80bfa6fbeb5fa3255b830c67fdfb7e703f", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4e516d131fde87b568abd62e1b14aa07ba7d5edfd230bab4e25cc9dedbb39135"},
11 | "phoenix_html": {:hex, :phoenix_html, "2.14.2", "b8a3899a72050f3f48a36430da507dd99caf0ac2d06c77529b1646964f3d563e", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "58061c8dfd25da5df1ea0ca47c972f161beb6c875cd293917045b92ffe1bf617"},
12 | "phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.2.7", "21564144897109ac486518651fecd09403a4d9df4d8432e7dcdf156df6a6a31a", [:mix], [{:phoenix_html, "~> 2.14.1 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.14.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.4.0 or ~> 0.5.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "2204c2c6755da7b39a21e312253b93d977cc846c85df8a6c0d9f9505cd8bf15b"},
13 | "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.4", "940c0344b1d66a2e46eef02af3a70e0c5bb45a4db0bf47917add271b76cd3914", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "38f9308357dea4cc77f247e216da99fcb0224e05ada1469167520bed4cb8cccd"},
14 | "phoenix_live_view": {:hex, :phoenix_live_view, "0.14.4", "7286a96287cd29b594ce4a7314249cea7311af04a06c0fa3e50932e188e73996", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.3", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 0.5", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "fc4f8cf205c784eeccee35de8afbfeb995ce5511ac4839db63d6d67a5ba091d1"},
15 | "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
16 | "plug": {:hex, :plug, "1.10.4", "41eba7d1a2d671faaf531fa867645bd5a3dce0957d8e2a3f398ccff7d2ef017f", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ad1e233fe73d2eec56616568d260777b67f53148a999dc2d048f4eb9778fe4a0"},
17 | "plug_cowboy": {:hex, :plug_cowboy, "2.3.0", "149a50e05cb73c12aad6506a371cd75750c0b19a32f81866e1a323dda9e0e99d", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bc595a1870cef13f9c1e03df56d96804db7f702175e4ccacdb8fc75c02a7b97e"},
18 | "plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"},
19 | "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
20 | "telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
21 | "telemetry_metrics": {:hex, :telemetry_metrics, "0.5.0", "1b796e74add83abf844e808564275dfb342bcc930b04c7577ab780e262b0d998", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "31225e6ce7a37a421a0a96ec55244386aec1c190b22578bd245188a4a33298fd"},
22 | "telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"},
23 | }
24 |
--------------------------------------------------------------------------------
/priv/gettext/en/LC_MESSAGES/errors.po:
--------------------------------------------------------------------------------
1 | ## `msgid`s in this file come from POT (.pot) files.
2 | ##
3 | ## Do not add, change, or remove `msgid`s manually here as
4 | ## they're tied to the ones in the corresponding POT file
5 | ## (with the same domain).
6 | ##
7 | ## Use `mix gettext.extract --merge` or `mix gettext.merge`
8 | ## to merge POT files into PO files.
9 | msgid ""
10 | msgstr ""
11 | "Language: en\n"
12 |
--------------------------------------------------------------------------------
/priv/gettext/errors.pot:
--------------------------------------------------------------------------------
1 | ## This is a PO Template file.
2 | ##
3 | ## `msgid`s here are often extracted from source code.
4 | ## Add new translations manually only if they're dynamic
5 | ## translations that can't be statically extracted.
6 | ##
7 | ## Run `mix gettext.extract` to bring this file up to
8 | ## date. Leave `msgstr`s empty as changing them here has no
9 | ## effect: edit them in PO (`.po`) files instead.
10 |
11 |
--------------------------------------------------------------------------------
/test/demo_web/live/page_live_test.exs:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.PageLiveTest do
2 | use DemoWeb.ConnCase
3 |
4 | import Phoenix.LiveViewTest
5 |
6 | test "disconnected and connected render", %{conn: conn} do
7 | {:ok, page_live, disconnected_html} = live(conn, "/")
8 | assert disconnected_html =~ "Welcome to Phoenix!"
9 | assert render(page_live) =~ "Welcome to Phoenix!"
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/test/demo_web/views/error_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.ErrorViewTest do
2 | use DemoWeb.ConnCase, async: true
3 |
4 | # Bring render/3 and render_to_string/3 for testing custom views
5 | import Phoenix.View
6 |
7 | test "renders 404.html" do
8 | assert render_to_string(DemoWeb.ErrorView, "404.html", []) == "Not Found"
9 | end
10 |
11 | test "renders 500.html" do
12 | assert render_to_string(DemoWeb.ErrorView, "500.html", []) == "Internal Server Error"
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/test/demo_web/views/layout_view_test.exs:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.LayoutViewTest do
2 | use DemoWeb.ConnCase, async: true
3 |
4 | # When testing helpers, you may want to import Phoenix.HTML and
5 | # use functions such as safe_to_string() to convert the helper
6 | # result into an HTML string.
7 | # import Phoenix.HTML
8 | end
9 |
--------------------------------------------------------------------------------
/test/support/channel_case.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.ChannelCase do
2 | @moduledoc """
3 | This module defines the test case to be used by
4 | channel tests.
5 |
6 | Such tests rely on `Phoenix.ChannelTest` and also
7 | import other functionality to make it easier
8 | to build common data structures and query the data layer.
9 |
10 | Finally, if the test case interacts with the database,
11 | we enable the SQL sandbox, so changes done to the database
12 | are reverted at the end of every test. If you are using
13 | PostgreSQL, you can even run database tests asynchronously
14 | by setting `use DemoWeb.ChannelCase, async: true`, although
15 | this option is not recommended for other databases.
16 | """
17 |
18 | use ExUnit.CaseTemplate
19 |
20 | using do
21 | quote do
22 | # Import conveniences for testing with channels
23 | import Phoenix.ChannelTest
24 | import DemoWeb.ChannelCase
25 |
26 | # The default endpoint for testing
27 | @endpoint DemoWeb.Endpoint
28 | end
29 | end
30 |
31 | setup _tags do
32 | :ok
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/test/support/conn_case.ex:
--------------------------------------------------------------------------------
1 | defmodule DemoWeb.ConnCase do
2 | @moduledoc """
3 | This module defines the test case to be used by
4 | tests that require setting up a connection.
5 |
6 | Such tests rely on `Phoenix.ConnTest` and also
7 | import other functionality to make it easier
8 | to build common data structures and query the data layer.
9 |
10 | Finally, if the test case interacts with the database,
11 | we enable the SQL sandbox, so changes done to the database
12 | are reverted at the end of every test. If you are using
13 | PostgreSQL, you can even run database tests asynchronously
14 | by setting `use DemoWeb.ConnCase, async: true`, although
15 | this option is not recommended for other databases.
16 | """
17 |
18 | use ExUnit.CaseTemplate
19 |
20 | using do
21 | quote do
22 | # Import conveniences for testing with connections
23 | import Plug.Conn
24 | import Phoenix.ConnTest
25 | import DemoWeb.ConnCase
26 |
27 | alias DemoWeb.Router.Helpers, as: Routes
28 |
29 | # The default endpoint for testing
30 | @endpoint DemoWeb.Endpoint
31 | end
32 | end
33 |
34 | setup _tags do
35 | {:ok, conn: Phoenix.ConnTest.build_conn()}
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/test/test_helper.exs:
--------------------------------------------------------------------------------
1 | ExUnit.start()
2 |
--------------------------------------------------------------------------------