This will be a fairly simple and straightforward app, but I will try to touch on as many Phoenix concepts as possible. Hope you will like it and learn something new. Lets start today with what we need to install in order to be able to create a new Phoenix project. Than we will add a couple of tools, that will help us with testing. Install TailwindCSS, change default font. We will end with clearing the boilerplate code, our first test and committing everything to Github.
Code is available at milica-golocorbin/casting_vote.
Installation
Phoenix is a web development framework written in Elixir. And is based on the server-side Model View Controller (MVC) pattern. To build a Phoenix application, we will need a few dependencies:
Erlang VM and the Elixir programming language
PostgreSQL database
Hex package manager (Hex is used for installation of dependencies we might need in our project.)
mix local.hex
Once we have Elixir and Erlang, PostgreSQL and Hex installed, we can install the Phoenix application generator:
mix archive.install hex phx_new
At the moment of writing this blog, Phoenix 1.7 is available. Since I already started writing this project with 1.6, I will continue with it. But along the way I will see to migrate the project to 1.7.
Project creation
If you are not sure about which command to use you can always use mix help to see all available commands. To shorten the list and find command necessary for bootstrapping new Phoenix app use:
mix help | grep phx
mix help phx.new
mix phx.new casting_vote --binary-id
We'll use binary_id for primary key type in Ecto schemas.
Phoenix assumes that the database has a user account with name: postgres and with the password postgres. If that is not the case, changes can be made in the config/dev.exs file.
Adding Credo, Mix test.watch, ExCoveralls
We will use credo for static code analyses and code consistency. It is a great tool for following the standards and best practices of elixir.
Mix test.watch is great for automatically running our tests. So we don't have to constantly call mix.test, whenever we test something.
We will use ExCoveralls as a test coverage tool. It will show us how many percent of our code is covered by tests.
mix.exs
# Add to dependencies list:
defp deps do
[
...
{:credo, "~> 1.6", only: [:dev, :test], runtime: false},
{:mix_test_watch, "~> 1.0", only: [:dev, :test], runtime:
false},
{:excoveralls, "~> 0.10", only: :test}
]
end
# Add the following parameters into project:
def project do
[
...
test_coverage: [tool: ExCoveralls],
preferred_cli_env: [
"test.watch": :test,
coveralls: :test,
"coveralls.detail": :test,
"coveralls.post": :test,
"coveralls.html": :test
]
]
end
# Fetch dependencies:
mix deps.get
credo
# Run task:
mix credo -a --strict
- Modules should have a @moduledoc tag.
Either go into each module and add documentation or add at the top: @moduledoc false
- Nested modules could be aliased at the top of the invoking module.
test/support/data_case.ex
Inside the file add alias Ecto.Adapters.SQL.Sandbox on the top. So we can remove nested modules from the function that was the issue.
mix test.watch
# Run task:
mix test.watch
At the moment all the tests that were created when we bootstrapped our project are passing, because we haven't made any changes yet.
coveralls
# Run task:
MIX_ENV=test mix coveralls
# Run task to generate html:
mix coveralls.html
First command prints test coverage percent in the console. And the second one will give us a graphical representation.
We can also add files, to be skipped during code coverage calculation. We can add files autogenerated by Phoenix that we are not planning to change. In case we decide to do something with them, we can simply remove them from coveralls.json. This file needs to be created at the root.
coveralls.json
{
"skip_files": [
"lib/casting_vote_web.ex",
"lib/casting_vote.ex",
"lib/casting_vote/application.ex",
"lib/casting_vote/mailer.ex",
"lib/casting_vote/repo.ex",
"lib/casting_vote_web/telemetry.ex",
"lib/casting_vote_web/gettext.ex",
"lib/casting_vote_web/views/error_helpers.ex",
"test/support/conn_case.ex",
"test/support/data_case.ex"
]
}
router.ex
At the moment in the MISSED column next to routes, we have 2. To solve that, we can use comments # coveralls-ignore-start and # coveralls-ignore-stop in the router file to ignore LiveDashboard and Swoosh mailbox preview from code coverage calculation. Just add the start comment before this block of code and after.
At the moment I will also put pipeline api in the comment. Later, if I decide to use it, we can remove the comment.
Installing Tailwind CSS
Follow instructions from Install Tailwind CSS with Phoenix.
Adding fonts
layout/root.html.heex
In the head tag add:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=League+Spartan:wght@400;600;700&display=swap" rel="stylesheet">
tailwind.config.js
We need to tell Tailwind to use "League Spartan font". At the top of the file add defaultTheme constant.
const defaultTheme = require("tailwindcss/defaultTheme");
theme: {
extend: {
fontFamily: {
sans: ["League Spartan", ...defaultTheme.fontFamily.sans],
},
},
},
Clean up generated boilerplate code. Fix the failing test.
layout/root.html.heex
<header>
<section>
<div>
<%= link "home", to: Routes.page_path(@conn, :index) %>
</div>
</section>
</header>
page/index.html.heex
<section>
<h1 class="text-4xl font-bold">Casting Vote App</h1>
</section>
If we run mix test.watch now we will see our first failing test, because we changed our h1 tag in the page/index.html.heex.
test/casting_vote_web/controllers/page_controller_test.exs
assert html_response(conn, 200) =~ "Casting Vote App"
Commit to github
git init
git add .
git commit -m "Added credo, excoveralls, mix_test_watch, tailwind and different font. Cleaned up boilerplate."
Top comments (0)