Skip to content

Commit 531160f

Browse files
committedApr 29, 2024
Move README docs to PhoenixTest (and augment)
What changed? ============ The library's surface area is too small for a separate README as an "introduction" in ExDoc's "Pages" section. More often than not, we want to find the setup, installation, etc. AND the exact function definitions. For that reason, we move the README docs into the `PhoenixTest` module. And as we do so, we take the opportunity to update them with a couple of sections on filling out forms.
1 parent 8385f07 commit 531160f

File tree

3 files changed

+186
-122
lines changed

3 files changed

+186
-122
lines changed
 

‎README.md

+4-105
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ test "admin can create a user", %{conn: conn} do
2121
conn
2222
|> visit("/")
2323
|> click_link("Users")
24-
|> fill_form("#user-form", name: "Aragorn", email: "aragorn@dunedain.com")
24+
|> fill_in("Name", with: "Aragorn")
2525
|> click_button("Create")
2626
|> assert_has(".user", text: "Aragorn")
2727
end
@@ -31,102 +31,7 @@ Note that PhoenixTest does not handle JavaScript. If you're looking for
3131
something that supports JavaScript, take a look at
3232
[Wallaby](https://hexdocs.pm/wallaby/readme.html).
3333

34-
## Setup
35-
36-
PhoenixTest requires Phoenix `1.7+` and LiveView `0.20+`. It may work with
37-
earlier versions, but I have not tested that.
38-
39-
### Installation
40-
41-
Add `phoenix_test` to your list of dependencies in `mix.exs`:
42-
43-
```elixir
44-
def deps do
45-
[
46-
{:phoenix_test, "~> 0.2.12", only: :test, runtime: false}
47-
]
48-
end
49-
```
50-
51-
### Configuration
52-
53-
In `config/test.exs` specify the endpoint to be used for routing requests:
54-
55-
```elixir
56-
config :phoenix_test, :endpoint, MyAppWeb.Endpoint
57-
```
58-
59-
### Adding a `FeatureCase`
60-
61-
`PhoenixTest` helpers can be included via `import PhoenixTest`.
62-
63-
But since each test needs a `conn` struct to get started, you'll likely want to
64-
set up a few things before that.
65-
66-
To make that easier, it's helpful to create a `FeatureCase` module that can be
67-
used from your tests (replace `MyApp` with your app's name):
68-
69-
```elixir
70-
defmodule MyAppWeb.FeatureCase do
71-
@moduledoc """
72-
This module defines the test case to be used by tests that require setting up
73-
a connection to test feature tests.
74-
75-
Such tests rely on `PhoenixTest` and also import other functionality to
76-
make it easier to build common data structures and interact with pages.
77-
78-
Finally, if the test case interacts with the database, we enable the SQL
79-
sandbox, so changes done to the database are reverted at the end of every
80-
test. If you are using PostgreSQL, you can even run database tests
81-
asynchronously by setting `use MyAppWeb.FeatureCase, async: true`, although
82-
this option is not recommended for other databases.
83-
"""
84-
85-
use ExUnit.CaseTemplate
86-
87-
using do
88-
quote do
89-
use MyAppWeb, :verified_routes
90-
91-
import MyAppWeb.FeatureCase
92-
93-
import PhoenixTest
94-
end
95-
end
96-
97-
setup tags do
98-
pid = Ecto.Adapters.SQL.Sandbox.start_owner!(MyApp.Repo, shared: not tags[:async])
99-
on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end)
100-
101-
{:ok, conn: Phoenix.ConnTest.build_conn()}
102-
end
103-
end
104-
```
105-
106-
Note that we assume your Phoenix project is using Ecto and its phenomenal
107-
`SQL.Sandbox`. If it doesn't, feel free to remove the `SQL.Sandbox` code above.
108-
109-
## Usage
110-
111-
Now, you can create your tests like this:
112-
113-
```elixir
114-
# test/my_app_web/features/admin_can_create_user_test.exs
115-
116-
defmodule MyAppWeb.AdminCanCreateUserTest do
117-
use MyAppWeb.FeatureCase, async: true
118-
119-
test "admin can create user", %{conn: conn} do
120-
conn
121-
|> visit("/")
122-
|> click_link("Users")
123-
|> fill_form("#user-form", name: "Aragorn", email: "aragorn@dunedain.com")
124-
|> click_button("Create")
125-
|> assert_has(".user", text: "Aragorn")
126-
end
127-
```
128-
129-
For full documentation, take a look at [PhoenixTest module docs](https://hexdocs.pm/phoenix_test/PhoenixTest.html).
34+
For full documentation, take a look at [PhoenixTest docs](https://hexdocs.pm/phoenix_test/PhoenixTest.html).
13035

13136
## Why PhoenixTest?
13237

@@ -205,13 +110,7 @@ pages -- pages that were normal prior to the advent of LiveView and which are
205110
sometimes called "dead" views. Thus, we do not mean _static_ in the sense that
206111
static-site generators (such as Jekyll, Gatsby, etc.) mean it.
207112

208-
## Sponsors
209113

210-
Made possible thanks to:
114+
**Made with ❤️ by [German Velasco]**
211115

212-
<a href="https://www.elixirstreams.com">
213-
<figure>
214-
<img height="100" width="100" src="https://www.elixirstreams.com/assets/images/elixir-streams-logo-transparent.png">
215-
<figcaption>Elixir Streams</figcaption>
216-
</figure>
217-
</a>
116+
[German Velasco]: https://germanvelasco.com

‎lib/phoenix_test.ex

+181-15
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,197 @@
11
defmodule PhoenixTest do
22
@moduledoc """
3-
PhoenixTest provides a unified way of writing feature tests -- regardless of
4-
whether you're testing LiveView pages or static pages.
3+
PhoenixTest provides a unified way of writing feature tests -- regardless of
4+
whether you're testing LiveView pages or static pages.
55
6-
It also handles navigation between LiveView and static pages seamlessly. So, you
7-
don't have to worry about what type of page you're visiting. Just write the
8-
tests from the user's perspective.
6+
It also handles navigation between LiveView and static pages seamlessly. So, you
7+
don't have to worry about what type of page you're visiting. Just write the
8+
tests from the user's perspective.
99
10-
Thus, you can test a flow going from static to LiveView pages and back without
11-
having to worry about the underlying implementation.
10+
Thus, you can test a flow going from static to LiveView pages and back without
11+
having to worry about the underlying implementation.
1212
13-
This is a sample flow:
13+
This is a sample flow:
1414
15-
```elixir
16-
test "admin can create a user", %{conn: conn} do
15+
```elixir
16+
test "admin can create a user", %{conn: conn} do
17+
conn
18+
|> visit("/")
19+
|> click_link("Users")
20+
|> fill_in("Name", with: "Aragorn")
21+
|> choose("Ranger")
22+
|> assert_has(".user", text: "Aragorn")
23+
end
24+
```
25+
26+
Note that PhoenixTest does _not_ handle JavaScript. If you're looking for
27+
something that supports JavaScript, take a look at
28+
[Wallaby](https://hexdocs.pm/wallaby/readme.html).
29+
30+
## Setup
31+
32+
PhoenixTest requires Phoenix `1.7+` and LiveView `0.20+`. It may work with
33+
earlier versions, but I have not tested that.
34+
35+
### Installation
36+
37+
Add `phoenix_test` to your list of dependencies in `mix.exs`:
38+
39+
```elixir
40+
def deps do
41+
[
42+
{:phoenix_test, "~> 0.2.12", only: :test, runtime: false}
43+
]
44+
end
45+
```
46+
47+
### Configuration
48+
49+
In `config/test.exs` specify the endpoint to be used for routing requests:
50+
51+
```elixir
52+
config :phoenix_test, :endpoint, MyAppWeb.Endpoint
53+
```
54+
55+
### Getting `PhoenixTest` helpers
56+
57+
`PhoenixTest` helpers can be included via `import PhoenixTest`.
58+
59+
But since each test needs a `conn` struct to get started, you'll likely want
60+
to set up a few things before that.
61+
62+
There are two ways to do that.
63+
64+
### With `ConnCase`
65+
66+
If you plan to use `ConnCase` solely for `PhoenixTest`, then you can import
67+
the helpers there:
68+
69+
```elixir
70+
using do
71+
quote do
72+
# importing other things for ConnCase
73+
74+
import PhoenixTest
75+
76+
# doing other setup for ConnCase
77+
end
78+
end
79+
```
80+
81+
### Adding a `FeatureCase`
82+
83+
If you want to create your own `FeatureCase` helper module like `ConnCase`,
84+
you can copy the code below which can be `use`d from your tests (replace
85+
`MyApp` with your app's name):
86+
87+
```elixir
88+
defmodule MyAppWeb.FeatureCase do
89+
use ExUnit.CaseTemplate
90+
91+
using do
92+
quote do
93+
use MyAppWeb, :verified_routes
94+
95+
import MyAppWeb.FeatureCase
96+
97+
import PhoenixTest
98+
end
99+
end
100+
101+
setup tags do
102+
pid = Ecto.Adapters.SQL.Sandbox.start_owner!(MyApp.Repo, shared: not tags[:async])
103+
on_exit(fn -> Ecto.Adapters.SQL.Sandbox.stop_owner(pid) end)
104+
105+
{:ok, conn: Phoenix.ConnTest.build_conn()}
106+
end
107+
end
108+
```
109+
110+
Note that we assume your Phoenix project is using Ecto and its phenomenal
111+
`SQL.Sandbox`. If it doesn't, feel free to remove the `SQL.Sandbox` code
112+
above.
113+
114+
## Usage
115+
116+
Now that we have all the setup out of the way, we can create tests like
117+
this:
118+
119+
```elixir
120+
# test/my_app_web/features/admin_can_create_user_test.exs
121+
122+
defmodule MyAppWeb.AdminCanCreateUserTest do
123+
use MyAppWeb.FeatureCase, async: true
124+
125+
test "admin can create user", %{conn: conn} do
17126
conn
18127
|> visit("/")
19128
|> click_link("Users")
20-
|> fill_form("#user-form", name: "Aragorn", email: "aragorn@dunedan.com")
129+
|> fill_in("Name", with: "Aragorn")
130+
|> fill_in("Email", with: "aragorn@dunedain.com")
21131
|> click_button("Create")
22132
|> assert_has(".user", text: "Aragorn")
23133
end
24-
```
134+
end
135+
```
136+
137+
### Filling out forms
138+
139+
We can fill out forms by targetting their inputs, selects, etc. by label:
140+
141+
```elixir
142+
test "admin can create user", %{conn: conn} do
143+
conn
144+
|> visit("/")
145+
|> click_link("Users")
146+
|> fill_in("Name", with: "Aragorn")
147+
|> select("Elessar", from: "Aliases")
148+
|> choose("Human") # <- choose a radio option
149+
|> check("Ranger") # <- check a checkbox
150+
|> click_button("Create")
151+
|> assert_has(".user", text: "Aragorn")
152+
end
153+
```
154+
155+
For more info, see `fill_in/3`, `select/3`, `choose/2`, `check/2`,
156+
`uncheck/2`.
157+
158+
### Submitting forms without clicking a button
159+
160+
Once we've filled out a form, you can click a button with
161+
`click_button/2` to submit the form. But sometimes you want to emulate what
162+
would happen by just pressing <Enter>.
163+
164+
For that case, you can use `submit/1` to submit the form you just filled
165+
out.
166+
167+
```elixir
168+
session
169+
|> fill_in("Name", with: "Aragorn")
170+
|> check("Ranger")
171+
|> submit()
172+
```
173+
174+
For more info, see `submit/1`.
175+
176+
### Targeting which form to fill out
177+
178+
If you find yourself in a situation where you have multiple forms with the
179+
same labels (even when those labels point to different inputs), then you
180+
might have to scope your form-filling.
181+
182+
To do that, you can scope all of the form helpers using `within/3`:
183+
184+
```elixir
185+
session
186+
|> within("#user-form", fn session ->
187+
session
188+
|> fill_in("Name", with: "Aragorn")
189+
|> check("Ranger")
190+
|> click_button("Create")
191+
end)
192+
```
25193
26-
Note that PhoenixTest does _not_ handle JavaScript. If you're looking for
27-
something that supports JavaScript, take a look at
28-
[Wallaby](https://hexdocs.pm/wallaby/readme.html).
194+
For more info, see `within/3`.
29195
"""
30196

31197
import Phoenix.ConnTest

‎mix.exs

+1-2
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,8 @@ defmodule PhoenixTest.MixProject do
5757

5858
defp docs do
5959
[
60-
main: "readme",
60+
main: "PhoenixTest",
6161
extras: [
62-
"README.md": [title: "Introduction"],
6362
"CHANGELOG.md": [title: "Changelog"],
6463
"upgrade_guides.md": [title: "Upgrade Guides"]
6564
]

0 commit comments

Comments
 (0)
Please sign in to comment.