Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 55 additions & 168 deletions test/controllers/project_controller_test.exs
Original file line number Diff line number Diff line change
@@ -1,53 +1,31 @@
defmodule CodeCorps.ProjectControllerTest do
use CodeCorps.ApiCase
use CodeCorps.ApiCase, resource_name: :project

alias CodeCorps.Project
@valid_attrs %{title: "Valid project"}
@invalid_attrs %{title: ""}

@valid_attrs %{
title: "Valid project",
description: "Valid project description",
long_description_markdown: "Valid **markdown**"
}

@invalid_attrs %{
title: ""
}

defp build_payload, do: %{ "data" => %{"type" => "project"}}

describe "#index" do
describe "index" do
test "lists all entries on index", %{conn: conn} do
path = conn |> project_path(:index)
json = conn |> get(path) |> json_response(200)
[project_1, project_2] = insert_pair(:project)

assert json["data"] == []
conn
|> request_index
|> json_response(200)
|> assert_ids_from_response([project_1.id, project_2.id])
end

test "lists all entries for organization specified by slug", %{conn: conn} do
organization_slug = "test-organization"
organization = insert(:organization, name: "Test Organization", slug: organization_slug)
insert(:slugged_route, organization: organization, slug: organization_slug)
project_1 = insert(:project, title: "Test Project 1", organization: organization)
project_2 = insert(:project, title: "Test Project 2", organization: organization)

conn = conn |> get("/#{organization_slug}/projects")

data = conn |> json_response(200) |> Map.get("data")

assert Enum.count(data) == 2
[project_1, project_2] = insert_pair(:project)

actual_ids =
data
|> Enum.map(& &1["id"])
|> Enum.map(&Integer.parse(&1) |> elem(0))
|> Enum.sort
path = ("/#{organization_slug}/projects")

expected_ids =
[project_1, project_2]
|> Enum.map(& &1.id)
|> Enum.sort

assert expected_ids == actual_ids
conn
|> get(path)
|> json_response(200)
|> assert_ids_from_response([project_1.id, project_2.id])
end

test "listing by organization slug is case insensitive", %{conn: conn} do
Expand All @@ -58,43 +36,28 @@ defmodule CodeCorps.ProjectControllerTest do
end
end

describe "#show" do
describe "show" do
test "shows chosen resource", %{conn: conn} do
project = insert(:project,
title: "Test project",
description: "Test project description",
long_description_markdown: "A markdown **description**")
project = insert(:project)

conn = get conn, project_path(conn, :show, project)
data = json_response(conn, 200)["data"]
assert data["id"] == "#{project.id}"
assert data["type"] == "project"
assert data["attributes"]["title"] == "Test project"
assert data["attributes"]["description"] == "Test project description"
assert data["attributes"]["long-description-markdown"] == "A markdown **description**"
assert data["relationships"]["organization"]["data"]["id"] == Integer.to_string(project.organization_id)
conn
|> request_show(project)
|> json_response(200)
|> Map.get("data")
|> assert_result_id(project.id)
end

test "shows chosen resource retrieved by slug", %{conn: conn} do
project = insert(:project,
title: "Test project",
description: "Test project description",
long_description_markdown: "A markdown **description**",
slug: "test-project")

conn = get conn, "/test-organization/test-project"
organization = insert(:organization)
project = insert(:project, organization: organization)

data =
conn
|> json_response(200)
|> Map.get("data")
path = "#{organization.slug}/#{project.slug}"

assert data["id"] == "#{project.id}"
assert data["type"] == "project"
assert data["attributes"]["title"] == "Test project"
assert data["attributes"]["description"] == "Test project description"
assert data["attributes"]["long-description-markdown"] == "A markdown **description**"
assert data["relationships"]["organization"]["data"]["id"] == Integer.to_string(project.organization_id)
conn
|> get(path)
|> json_response(200)
|> Map.get("data")
|> assert_result_id(project.id)
end

test "retrieval by slug is case insensitive", %{conn: conn} do
Expand All @@ -110,138 +73,62 @@ defmodule CodeCorps.ProjectControllerTest do
test "creates and renders resource when attributes are valid", %{conn: conn, current_user: current_user} do
organization = insert(:organization)
insert(:organization_membership, role: "admin", member: current_user, organization: organization)

payload =
build_payload
|> put_attributes(@valid_attrs)
|> put_relationships(organization)

path = conn |> project_path(:create)

json = conn |> post(path, payload) |> json_response(201)

id = json["data"]["id"]
assert id
project = Project |> Repo.get(id)

assert project
assert project.title == "Valid project"
assert project.description == "Valid project description"
assert project.long_description_markdown == "Valid **markdown**"
assert project.long_description_body == "<p>Valid <strong>markdown</strong></p>\n"
assert project.organization_id == organization.id
attrs = @valid_attrs |> Map.merge(%{organization: organization})
assert conn |> request_create(attrs) |> json_response(201)
end

@tag :authenticated
test "does not create resource and renders errors when attributes are invalid", %{conn: conn, current_user: current_user} do
organization = insert(:organization)
insert(:organization_membership, role: "admin", member: current_user, organization: organization)

payload =
build_payload
|> put_attributes(@invalid_attrs)
|> put_relationships(organization)

path = conn |> project_path(:create)

errors = conn |> post(path, payload) |> json_response(422) |> Map.get("errors")

assert errors != %{}
@tag authenticated: :admin
test "renders 422 when attributes are invalid", %{conn: conn} do
assert conn |> request_create(@invalid_attrs) |> json_response(422)
end

test "does not create resource and renders 401 when unauthenticated", %{conn: conn} do
path = conn |> project_path(:create)
assert conn |> post(path) |> json_response(401)
test "renders 401 when unauthenticated", %{conn: conn} do
assert conn |> request_create |> json_response(401)
end

@tag :authenticated
test "does not create resource and renders 403 when not authorized", %{conn: conn, current_user: current_user} do
organization = insert(:organization)
insert(:organization_membership, role: "contributor", member: current_user, organization: organization)

payload =
build_payload
|> put_attributes(@valid_attrs)
|> put_relationships(organization)

path = conn |> project_path(:create)
assert conn |> post(path, payload) |> json_response(403)
test "renders 403 when not authorized", %{conn: conn} do
# Need the organization in order to access membership in the project policy
attrs = %{organization: insert(:organization)}
assert conn |> request_create(attrs) |> json_response(403)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you doing this extra work here? Would request_create on its own not work?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was having trouble getting this test to pass and this was the only solution that worked. I couldn't figure out why the usual request_create wasn't working so I just included the attributes. I'll look at it again today.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's the error I'm getting: ** (FunctionClauseError) no function clause matching in CodeCorps.Helpers.Policy.get_membership/2

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay we'll dig into it when we pair.

end
end

describe "update" do

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks so much better 👏

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

This is what I love the most about these.

@tag authenticated: :admin
test "updates and renders resource when attributes are valid", %{conn: conn} do
project = insert(:project)

payload = build_payload |> put_id(project.id) |> put_attributes(@valid_attrs)
path = conn |> project_path(:update, project)

json = conn |> put(path, payload) |> json_response(200)

id = json["data"]["id"]
assert id

project = Project |> Repo.get(id)

assert project
assert project.title == "Valid project"
assert project.description == "Valid project description"
assert project.long_description_markdown == "Valid **markdown**"
assert project.long_description_body == "<p>Valid <strong>markdown</strong></p>\n"
assert project.organization_id
assert conn |> request_update(@valid_attrs) |> json_response(200)
end

@tag authenticated: :admin
test "renders errors when attributes are invalid", %{conn: conn} do
project = insert(:project)

payload = build_payload |> put_id(project.id) |> put_attributes(@invalid_attrs)
path = conn |> project_path(:update, project)

errors = conn |> put(path, payload) |> json_response(422) |> Map.get("errors")

assert errors != %{}
assert conn |> request_update(@invalid_attrs) |> json_response(422)
end

@tag :requires_env
@tag authenticated: :admin
test "uploads a icon to S3", %{conn: conn} do
project = insert(:project)

organization = insert(:organization)
icon_data = "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="
attrs = Map.put(@valid_attrs, :base64_icon_data, icon_data)
attrs = @valid_attrs |> Map.merge(%{base64_icon_data: icon_data, organization: organization})

payload = build_payload |> put_id(project.id) |> put_attributes(attrs)
path = conn |> project_path(:update, project)

json = conn |> put(path, payload) |> json_response(200)

data = json["data"]
large_url = data["attributes"]["icon-large-url"]
assert large_url
assert String.contains? large_url, "/projects/#{project.id}/large"
thumb_url = data["attributes"]["icon-thumb-url"]
assert thumb_url
assert String.contains? thumb_url, "/projects/#{project.id}/thumb"
assert conn |> request_create(attrs) |> json_response(201)
end

test "does not create resource and renders 401 when unauthenticated", %{conn: conn} do
path = conn |> project_path(:update, "id not important")
assert conn |> put(path) |> json_response(401)
test "renders 401 when unauthenticated", %{conn: conn} do
assert conn |> request_update |> json_response(401)
end

@tag :authenticated
test "does not create resource and renders 403 when not authorized", %{conn: conn} do
project = insert(:project)
path = conn |> project_path(:update, project)
assert conn |> put(path) |> json_response(403)
test "renders 403 when not authorized", %{conn: conn} do
# Need the organization in order to access membership in the project policy
attrs = %{organization: insert(:organization)}
assert conn |> request_update(attrs) |> json_response(403)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, why not just request_update?

end

@tag :authenticated
test "does not update resource and renders 404 when not found", %{conn: conn} do
path = conn |> project_path(:update, -1)
assert conn |> put(path) |> json_response(404)
@tag authenticated: :admin
test "renders 404 when not found", %{conn: conn} do
assert conn |> request_update(:not_found) |> json_response(404)
end
end
end