$ mix phoenix.gen.model Role roles name:string admin:boolean
* creating web/models/role.ex * creating test/models/role_test.exs * creating priv/repo/migrations/20160721151158_create_role.exs Remember to update your repository by running migrations: $ mix ecto.migrate
mix ecto.migrate
. Based on the assumption that our database is configured properly, we should see a similar conclusion: Compiling 21 files (.ex) Generated pxblog app 11:12:04.736 [info] == Running Pxblog.Repo.Migrations.CreateRole.change/0 forward 11:12:04.736 [info] create table roles 11:12:04.742 [info] == Migrated in 0.0s
web/models/user.ex
as written below. belongs_to :role, Pxblog.Role
web/models/role.ex
and add the following line to the "roles" section of the schema: has_many :users, Pxblog.User
$ mix ecto.gen.migration add_role_id_to_users
Compiling 5 files (.ex) * creating priv/repo/migrations * creating priv/repo/migrations/20160721184919_add_role_id_to_users.exs
defmodule Pxblog.Repo.Migrations.AddRoleIdToUsers do use Ecto.Migration def change do end end
alter table(:users) do add :role_id, references(:roles) end
create index(:users, [:role_id])
mix ecto.migrate
again. Migration must be successful! If we run the tests now, they will all be green again!web/models/user.ex
as follows (note the addition : role_id in two places): def changeset(struct, params \\ %{}) do struct |> cast(params, [:username, :email, :password, :password_confirmation, :role_id]) |> validate_required([:username, :email, :password, :password_confirmation, :role_id]) |> hash_password end
test/support/test_helper.ex
and fill it with the following code: defmodule Pxblog.TestHelper do alias Pxblog.Repo alias Pxblog.User alias Pxblog.Role alias Pxblog.Post import Ecto, only: [build_assoc: 2] def create_role(%{name: name, admin: admin}) do Role.changeset(%Role{}, %{name: name, admin: admin}) |> Repo.insert end def create_user(role, %{email: email, username: username, password: password, password_confirmation: password_confirmation}) do role |> build_assoc(:users) |> User.changeset(%{email: email, username: username, password: password, password_confirmation: password_confirmation}) |> Repo.insert end def create_post(user, %{title: title, body: body}) do user |> build_assoc(:posts) |> Post.changeset(%{title: title, body: body}) |> Repo.insert end end
Repo.insert
function Repo.insert
, then we’ll get the standard answer {:ok, model}
when the addition is successful. In other words, this is simply the insertion of a Role revision.Repo.insert()
function and everything is ready!test/models/user_test.exs
. First we need to add alias Pxblog.TestHelper
to the very top of the module definition, which will allow us to use convenient helpers that we created a little earlier. Then we will create a setup block before the tests to reuse the role. setup do {:ok, role} = TestHelper.create_role(%{name: "user", admin: false}) {:ok, role: role} end
defp valid_attrs(role) do Map.put(@valid_attrs, :role_id, role.id) end test "changeset with valid attributes", %{role: role} do changeset = User.changeset(%User{}, valid_attrs(role)) assert changeset.valid? end
test/models/user_test.exs
.test/controllers/user_controller_test.exs
. To pass tests from it, we will use the same lessons. At the very top, add the alias Pxblog.Role
instruction, as well as the alias Pxblog.TestHelper
next. Then we place the setup block in which the role is created and the conn object is returned : setup do {:ok, user_role} = TestHelper.create_role(%{name: "user", admin: false}) {:ok, admin_role} = TestHelper.create_role(%{name: "admin", admin: true}) {:ok, conn: build_conn(), user_role: user_role, admin_role: admin_role} end
defp valid_create_attrs(role) do Map.put(@valid_create_attrs, :role_id, role.id) end
test "creates resource and redirects when data is valid", %{conn: conn, user_role: user_role} do conn = post conn, user_path(conn, :create), user: valid_create_attrs(user_role) assert redirected_to(conn) == user_path(conn, :index) assert Repo.get_by(User, @valid_attrs) end test "updates chosen resource and redirects when data is valid", %{conn: conn, user_role: user_role} do user = Repo.insert! %User{} conn = put conn, user_path(conn, :update, user), user: valid_create_attrs(user_role) assert redirected_to(conn) == user_path(conn, :show, user) assert Repo.get_by(User, @valid_attrs) end
mix test
still shows errors.test/controllers/post_controller_test.exs
: alias Pxblog.Role alias Pxblog.TestHelper
setup do {:ok, role} = TestHelper.create_role(%{name: "User Role", admin: false}) {:ok, user} = TestHelper.create_user(role, %{email: "test@test.com", username: "testuser", password: "test", password_confirmation: "test"}) {:ok, post} = TestHelper.create_post(user, %{title: "Test Post", body: "Test Body"}) conn = build_conn() |> login_user(user) {:ok, conn: conn, user: user, role: role, post: post} end
test "redirects when trying to edit a post for a different user", %{conn: conn, user: user, role: role, post: post} do {:ok, other_user} = TestHelper.create_user(role, %{email: "test2@test.com", username: "test2", password: "test", password_confirmation: "test"}) conn = get conn, user_post_path(conn, :edit, other_user, post) assert get_flash(conn, :error) == "You are not authorized to modify that post!" assert redirected_to(conn) == page_path(conn, :index) assert conn.halted end
defmodule Pxblog.PostControllerTest do use Pxblog.ConnCase alias Pxblog.Post alias Pxblog.TestHelper @valid_attrs %{body: "some content", title: "some content"} @invalid_attrs %{} setup do {:ok, role} = TestHelper.create_role(%{name: "User Role", admin: false}) {:ok, user} = TestHelper.create_user(role, %{email: "test@test.com", username: "testuser", password: "test", password_confirmation: "test"}) {:ok, post} = TestHelper.create_post(user, %{title: "Test Post", body: "Test Body"}) conn = build_conn() |> login_user(user) {:ok, conn: conn, user: user, role: role, post: post} end defp login_user(conn, user) do post conn, session_path(conn, :create), user: %{username: user.username, password: user.password} end test "lists all entries on index", %{conn: conn, user: user} do conn = get conn, user_post_path(conn, :index, user) assert html_response(conn, 200) =~ "Listing posts" end test "renders form for new resources", %{conn: conn, user: user} do conn = get conn, user_post_path(conn, :new, user) assert html_response(conn, 200) =~ "New post" end test "creates resource and redirects when data is valid", %{conn: conn, user: user} do conn = post conn, user_post_path(conn, :create, user), post: @valid_attrs assert redirected_to(conn) == user_post_path(conn, :index, user) assert Repo.get_by(assoc(user, :posts), @valid_attrs) end test "does not create resource and renders errors when data is invalid", %{conn: conn, user: user} do conn = post conn, user_post_path(conn, :create, user), post: @invalid_attrs assert html_response(conn, 200) =~ "New post" end test "shows chosen resource", %{conn: conn, user: user, post: post} do conn = get conn, user_post_path(conn, :show, user, post) assert html_response(conn, 200) =~ "Show post" end test "renders page not found when id is nonexistent", %{conn: conn, user: user} do assert_error_sent 404, fn -> get conn, user_post_path(conn, :show, user, -1) end end test "renders form for editing chosen resource", %{conn: conn, user: user, post: post} do conn = get conn, user_post_path(conn, :edit, user, post) assert html_response(conn, 200) =~ "Edit post" end test "updates chosen resource and redirects when data is valid", %{conn: conn, user: user, post: post} do conn = put conn, user_post_path(conn, :update, user, post), post: @valid_attrs assert redirected_to(conn) == user_post_path(conn, :show, user, post) assert Repo.get_by(Post, @valid_attrs) end test "does not update chosen resource and renders errors when data is invalid", %{conn: conn, user: user, post: post} do conn = put conn, user_post_path(conn, :update, user, post), post: %{"body" => nil} assert html_response(conn, 200) =~ "Edit post" end test "deletes chosen resource", %{conn: conn, user: user, post: post} do conn = delete conn, user_post_path(conn, :delete, user, post) assert redirected_to(conn) == user_post_path(conn, :index, user) refute Repo.get(Post, post.id) end test "redirects when the specified user does not exist", %{conn: conn} do conn = get conn, user_post_path(conn, :index, -1) assert get_flash(conn, :error) == "Invalid user!" assert redirected_to(conn) == page_path(conn, :index) assert conn.halted end test "redirects when trying to edit a post for a different user", %{conn: conn, role: role, post: post} do {:ok, other_user} = TestHelper.create_user(role, %{email: "test2@test.com", username: "test2", password: "test", password_confirmation: "test"}) conn = get conn, user_post_path(conn, :edit, other_user, post) assert get_flash(conn, :error) == "You are not authorized to modify that post!" assert redirected_to(conn) == page_path(conn, :index) assert conn.halted end end
test/controllers/session_controller_test.exs
file do not pass due to the fact that we did not tell them to start using our TestHelper . As before, add aliases to the top of the file and change the setup block: defmodule Pxblog.SessionControllerTest do use Pxblog.ConnCase alias Pxblog.User alias Pxblog.TestHelper setup do {:ok, role} = TestHelper.create_role(%{name: "user", admin: false}) {:ok, _user} = TestHelper.create_user(role, %{username: "test", password: "test", password_confirmation: "test", email: "test@test.com"}) {:ok, conn: build_conn()} end
1) test current user returns the user in the session (Pxblog.LayoutViewTest) test/views/layout_view_test.exs:13 Expected truthy, got nil code: LayoutView.current_user(conn) stacktrace: test/views/layout_view_test.exs:15 2) test current user returns nothing if there is no user in the session (Pxblog.LayoutViewTest) test/views/layout_view_test.exs:18 ** (ArgumentError) cannot convert nil to param stacktrace: (phoenix) lib/phoenix/param.ex:67: Phoenix.Param.Atom.to_param/1 (pxblog) web/router.ex:1: Pxblog.Router.Helpers.session_path/4 test/views/layout_view_test.exs:20
test/views/layout_view_test.exs
you can see how a user is created without a role! In the setup block, we also do not return this user, which leads to such sad consequences! Horror! So let's quickly refactor the entire file: defmodule Pxblog.LayoutViewTest do use Pxblog.ConnCase, async: true alias Pxblog.LayoutView alias Pxblog.TestHelper setup do {:ok, role} = TestHelper.create_role(%{name: "User Role", admin: false}) {:ok, user} = TestHelper.create_user(role, %{email: "test@test.com", username: "testuser", password: "test", password_confirmation: "test"}) {:ok, conn: build_conn(), user: user} end test "current user returns the user in the session", %{conn: conn, user: user} do conn = post conn, session_path(conn, :create), user: %{username: user.username, password: user.password} assert LayoutView.current_user(conn) end test "current user returns nothing if there is no user in the session", %{conn: conn, user: user} do conn = delete conn, session_path(conn, :delete, user) refute LayoutView.current_user(conn) end end
mix test
and ... test/controllers/post_controller_test.exs:20: warning: function create_user/0 is unused test/views/layout_view_test.exs:6: warning: unused alias Role test/views/layout_view_test.exs:5: warning: unused alias User test/controllers/user_controller_test.exs:5: warning: unused alias Role test/controllers/post_controller_test.exs:102: warning: variable user is unused test/controllers/post_controller_test.exs:6: warning: unused alias Role
$ mix test
......................................... Finished in 0.4 seconds 41 tests, 0 failures Randomized with seed 588307
priv/repo/seeds.exs
and paste the following code into it: alias Pxblog.Repo alias Pxblog.Role alias Pxblog.User role = %Role{} |> Role.changeset(%{name: "Admin Role", admin: true}) |> Repo.insert! admin = %User{} |> User.changeset(%{username: "admin", email: "admin@test.com", password: "test", password_confirmation: "test", role_id: role.id}) |> Repo.insert!
$ mix run priv/repo/seeds.exs
Source: https://habr.com/ru/post/315252/
All Articles