defmodule WaxxWeb.Api.V1.CardControllerTest do
use WaxxWeb.ConnCase, async: true
import Waxx.AccountsFixtures
import Waxx.KanbanFixtures
alias Waxx.Kanban
defp setup_owner do
user = confirmed_user_fixture()
board = board_fixture(user, name: "B")
%{user: user, board: board, token: api_token_fixture(user)}
end
defp auth(conn, token), do: put_req_header(conn, "authorization", "Bearer " <> token)
describe "POST /api/v1/boards/:id/cards" do
test "creates a card", %{conn: conn} do
%{token: token, board: board} = setup_owner()
conn =
conn
|> auth(token)
|> post(~p"/api/v1/boards/#{board.id}/cards", %{title: "Hello", description: "World"})
assert %{"card" => c} = json_response(conn, 201)
assert c["title"] == "Hello"
assert c["description"] == "World"
assert c["board_stage_id"]
end
test "validation_failed when title is missing", %{conn: conn} do
%{token: token, board: board} = setup_owner()
conn =
conn
|> auth(token)
|> post(~p"/api/v1/boards/#{board.id}/cards", %{description: "no title"})
assert json_response(conn, 422)["error"]["code"] == "validation_failed"
end
test "404 when caller isn't a member", %{conn: conn} do
%{token: token} = setup_owner()
other = confirmed_user_fixture()
other_board = board_fixture(other)
conn =
conn
|> auth(token)
|> post(~p"/api/v1/boards/#{other_board.id}/cards", %{title: "X"})
assert json_response(conn, 404)["error"]["code"] == "not_found"
end
test "403 when caller is a viewer", %{conn: conn} do
owner = confirmed_user_fixture()
viewer = confirmed_user_fixture()
board = board_fixture(owner)
{:ok, _} = Kanban.add_member(board, viewer, "viewer")
token = api_token_fixture(viewer)
conn =
conn
|> auth(token)
|> post(~p"/api/v1/boards/#{board.id}/cards", %{title: "X"})
assert json_response(conn, 403)["error"]["code"] == "forbidden"
end
end
describe "PATCH /api/v1/cards/:id" do
test "updates title + description", %{conn: conn} do
%{token: token, board: board, user: user} = setup_owner()
card = card_fixture(board, user, %{"title" => "old"})
conn =
conn
|> auth(token)
|> patch(~p"/api/v1/cards/#{card.id}", %{title: "new", description: "added"})
assert %{"card" => c} = json_response(conn, 200)
assert c["title"] == "new"
assert c["description"] == "added"
end
test "404 for someone else's card", %{conn: conn} do
owner = confirmed_user_fixture()
board = board_fixture(owner)
card = card_fixture(board, owner)
stranger = confirmed_user_fixture()
token = api_token_fixture(stranger)
conn =
conn
|> auth(token)
|> patch(~p"/api/v1/cards/#{card.id}", %{title: "x"})
assert json_response(conn, 404)
end
end
describe "POST /api/v1/cards/:id/move" do
test "moves along a valid transition", %{conn: conn} do
%{token: token, board: board, user: user} = setup_owner()
card = card_fixture(board, user)
[_todo, done] = board.stages
conn =
conn
|> auth(token)
|> post(~p"/api/v1/cards/#{card.id}/move", %{board_stage_id: done.id})
assert %{"card" => c} = json_response(conn, 200)
assert c["board_stage_id"] == done.id
end
test "422 invalid_transition for a backwards move", %{conn: conn} do
%{token: token, board: board, user: user} = setup_owner()
card = card_fixture(board, user)
[todo, done] = board.stages
# Step it forward first.
_ = post(auth(conn, token), ~p"/api/v1/cards/#{card.id}/move", %{board_stage_id: done.id})
conn =
conn
|> auth(token)
|> post(~p"/api/v1/cards/#{card.id}/move", %{board_stage_id: todo.id})
assert json_response(conn, 422)["error"]["code"] == "invalid_transition"
end
test "validation_failed without board_stage_id", %{conn: conn} do
%{token: token, board: board, user: user} = setup_owner()
card = card_fixture(board, user)
conn =
conn
|> auth(token)
|> post(~p"/api/v1/cards/#{card.id}/move", %{})
assert json_response(conn, 422)["error"]["code"] == "validation_failed"
end
end
describe "GET /api/v1/cards/:id" do
# 1x1 transparent PNG.
@png_data_url "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
test "detail payload carries a background once one is set", %{conn: conn} do
%{token: token, board: board, user: user} = setup_owner()
card = card_fixture(board, user)
# No background yet.
conn1 = conn |> auth(token) |> get(~p"/api/v1/cards/#{card.id}")
assert json_response(conn1, 200)["card"]["background"] == nil
{:ok, _} = Kanban.set_card_background(card, @png_data_url)
conn2 = build_conn() |> auth(token) |> get(~p"/api/v1/cards/#{card.id}")
assert %{"content_type" => "image/png", "data" => data} =
json_response(conn2, 200)["card"]["background"]
# Round-trips as decodable base64.
assert {:ok, _bytes} = Base.decode64(data)
end
end
describe "GET /api/v1/boards/:board_id/cards (background_version)" do
@png_data_url "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
test "lists background_version only for cards that have a background", %{conn: conn} do
%{token: token, board: board, user: user} = setup_owner()
with_bg = card_fixture(board, user, %{"title" => "art"})
without_bg = card_fixture(board, user, %{"title" => "plain"})
{:ok, _} = Kanban.set_card_background(with_bg, @png_data_url)
conn = conn |> auth(token) |> get(~p"/api/v1/boards/#{board.id}/cards")
cards = json_response(conn, 200)["cards"]
assert %{"background_version" => v} = Enum.find(cards, &(&1["id"] == with_bg.id))
assert is_integer(v)
assert %{"background_version" => nil} = Enum.find(cards, &(&1["id"] == without_bg.id))
end
end
describe "GET /api/v1/cards/:id/background" do
@png_data_url "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg=="
test "serves the image bytes with its content type to a member", %{conn: conn} do
%{token: token, board: board, user: user} = setup_owner()
card = card_fixture(board, user)
{:ok, bg} = Kanban.set_card_background(card, @png_data_url)
conn = conn |> auth(token) |> get(~p"/api/v1/cards/#{card.id}/background")
assert response(conn, 200) == bg.image_data
assert get_resp_header(conn, "content-type") |> hd() =~ "image/png"
end
test "404 when the card has no background", %{conn: conn} do
%{token: token, board: board, user: user} = setup_owner()
card = card_fixture(board, user)
conn = conn |> auth(token) |> get(~p"/api/v1/cards/#{card.id}/background")
assert json_response(conn, 404)["error"]["code"] == "not_found"
end
test "404 for a non-member", %{conn: conn} do
%{board: board, user: user} = setup_owner()
card = card_fixture(board, user)
{:ok, _} = Kanban.set_card_background(card, @png_data_url)
stranger = confirmed_user_fixture()
token = api_token_fixture(stranger)
conn = conn |> auth(token) |> get(~p"/api/v1/cards/#{card.id}/background")
assert json_response(conn, 404)["error"]["code"] == "not_found"
end
end
describe "DELETE /api/v1/cards/:id" do
test "deletes the card", %{conn: conn} do
%{token: token, board: board, user: user} = setup_owner()
card = card_fixture(board, user)
conn = conn |> auth(token) |> delete(~p"/api/v1/cards/#{card.id}")
assert response(conn, 204) == ""
refute Waxx.Repo.get(Waxx.Kanban.Card, card.id)
end
test "403 for a viewer", %{conn: conn} do
owner = confirmed_user_fixture()
viewer = confirmed_user_fixture()
board = board_fixture(owner)
{:ok, _} = Kanban.add_member(board, viewer, "viewer")
card = card_fixture(board, owner)
token = api_token_fixture(viewer)
conn = conn |> auth(token) |> delete(~p"/api/v1/cards/#{card.id}")
assert json_response(conn, 403)
end
end
end
neiam
/waxx
waxx
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
Log in to mark this repository.
8.3 KiB · text
History
a2252b9