Skip to content

Commit

Permalink
Move invite claim tracking to controller
Browse files Browse the repository at this point in the history
  • Loading branch information
begedin committed Jan 3, 2018
1 parent bb1f4c2 commit 561dfe2
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 65 deletions.
6 changes: 1 addition & 5 deletions lib/code_corps/accounts/accounts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ defmodule CodeCorps.Accounts do
alias CodeCorps.{
Accounts,
Accounts.Changesets,
Analytics,
Comment,
GitHub.Adapters,
GithubAppInstallation,
Expand All @@ -32,10 +31,7 @@ defmodule CodeCorps.Accounts do
"""
@spec create(map) :: {:ok, User.t} | {:error, Changeset.t} | {:error, :invite_not_found}
def create(%{"invite_id" => _} = params) do
with {:ok, %User{} = user, %UserInvite{} = user_invite} <- params |> Accounts.UserInvites.claim_invite() do
user.id |> Analytics.SegmentTracker.track("Claimed User Invite", user_invite)
{:ok, user}
end
params |> Accounts.UserInvites.claim_invite()
end
def create(%{} = params) do
%User{} |> User.registration_changeset(params) |> Repo.insert()
Expand Down
6 changes: 4 additions & 2 deletions lib/code_corps/accounts/user_invites.ex
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ defmodule CodeCorps.Accounts.UserInvites do

defp join_project(%User{}, %UserInvite{}), do: {:ok, nil}

@spec associate_invitee(UserInvite.t(), User.t()) :: ProjectUser.t()
@spec associate_invitee(UserInvite.t(), User.t()) :: {:ok, UserInvite.t()}
defp associate_invitee(%UserInvite{invitee: nil} = invite, %User{} = user) do
invite
|> Changeset.change(%{})
Expand All @@ -110,7 +110,9 @@ defmodule CodeCorps.Accounts.UserInvites do
end

@spec marshall_response(tuple) :: tuple
defp marshall_response({:ok, %{user: user, user_invite: user_invite}}), do: {:ok, user, user_invite}
defp marshall_response({:ok, %{user: user, user_invite: user_invite}}) do
{:ok, user |> Map.put(:claimed_invite, user_invite)}
end
defp marshall_response({:error, :load_invite, :not_found, _}), do: {:error, :invite_not_found}
defp marshall_response(other_tuple), do: other_tuple
end
1 change: 1 addition & 0 deletions lib/code_corps/model/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ defmodule CodeCorps.User do
field :username, :string
field :website, :string

has_one :claimed_invite, CodeCorps.UserInvite, foreign_key: :invitee_id
has_one :github_app_installation, CodeCorps.GithubAppInstallation
has_one :slugged_route, SluggedRoute

Expand Down
9 changes: 9 additions & 0 deletions lib/code_corps_web/controllers/user_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ defmodule CodeCorpsWeb.UserController do
Helpers.Query,
Services.UserService,
User,
UserInvite,
Accounts
}

Expand Down Expand Up @@ -38,6 +39,14 @@ defmodule CodeCorpsWeb.UserController do
@spec create(Conn.t(), map) :: Conn.t()
def create(%Conn{} = conn, %{} = params) do
with {:ok, %User{} = user} <- params |> Accounts.create() do
case user |> Map.get(:claimed_invite) do
%UserInvite{} = user_invite ->
user.id |> Analytics.SegmentTracker.track("Claimed User Invite", user_invite)

_other ->
nil
end

conn
|> put_status(:created)
|> render("show.json-api", data: user |> preload())
Expand Down
16 changes: 0 additions & 16 deletions test/lib/code_corps/accounts/accounts_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,6 @@ defmodule CodeCorps.AccountsTest do
assert Repo.get(User, user.id)
end

test "tracks invite claim with segment" do
invite = insert(:user_invite, invitee: nil, project: nil)

{:ok, %User{} = user} =
@valid_user_params
|> Map.put("invite_id", invite.id)
|> Accounts.create()

%{id: created_user_id} = Repo.get(User, user.id)

traits =
UserInvite |> Repo.get(invite.id) |> CodeCorps.Analytics.SegmentTraitsBuilder.build()

assert_received({:track, ^created_user_id, "Claimed User Invite", ^traits})
end

test "associates invite with user" do
invite = insert(:user_invite, invitee: nil, project: nil)

Expand Down
125 changes: 83 additions & 42 deletions test/lib/code_corps_web/controllers/user_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ defmodule CodeCorpsWeb.UserControllerTest do
describe "show" do
test "shows chosen resource", %{conn: conn} do
user = insert(:user)

conn
|> request_show(user)
|> json_response(200)
Expand All @@ -115,41 +116,48 @@ defmodule CodeCorpsWeb.UserControllerTest do
describe "create" do
test "creates and renders resource when data is valid", %{conn: conn} do
attrs = Map.put(@valid_attrs, :password, "password")
conn = post conn, user_path(conn, :create), %{
"data" => %{
"attributes" => attrs
}
}

conn =
post(conn, user_path(conn, :create), %{
"data" => %{
"attributes" => attrs
}
})

assert conn |> json_response(201)
end

test "calls segment tracking after user is created", %{conn: conn} do
conn = post conn, user_path(conn, :create), %{
"meta" => %{},
"data" => %{
"type" => "user",
"attributes" => Map.put(@valid_attrs, :password, "password"),
"relationships" => @relationships
}
}
id = json_response(conn, 201)["data"]["id"] |> String.to_integer
test "tracks user creation with segment", %{conn: conn} do
conn =
post(conn, user_path(conn, :create), %{
"meta" => %{},
"data" => %{
"type" => "user",
"attributes" => Map.put(@valid_attrs, :password, "password"),
"relationships" => @relationships
}
})

id = json_response(conn, 201)["data"]["id"] |> String.to_integer()
assert_received {:track, ^id, "Signed Up", %{}}
end

test "does not create resource and renders errors when data is invalid", %{conn: conn} do
attrs = Map.put(@invalid_attrs, :password, "password")
conn = post conn, user_path(conn, :create), %{
"data" => %{
"attributes" => attrs
}
}

conn =
post(conn, user_path(conn, :create), %{
"data" => %{
"attributes" => attrs
}
})

assert conn |> json_response(422)
end

test "supports claiming a user invite if specified by an id parameter", %{conn: conn} do
%{id: invite_id, email: email} = insert(:user_invite)

attrs =
@valid_attrs
|> Map.merge(%{email: email, invite_id: invite_id, password: "password"})
Expand All @@ -165,9 +173,31 @@ defmodule CodeCorpsWeb.UserControllerTest do
assert updated_invite.invitee_id == created_user.id
end

test "supports claiming a user invite to a project if specified by an id parameter", %{conn: conn} do
test "tracks invite claim with segment", %{conn: conn} do
%{id: invite_id, email: email} = invite = insert(:user_invite, invitee: nil, project: nil)

attrs =
@valid_attrs
|> Map.merge(%{email: email, invite_id: invite_id, password: "password"})

path = conn |> user_path(:create)
conn |> post(path, attrs)

%{invitee_id: invitee_id} = invite = UserInvite |> Repo.get(invite.id)

traits = invite |> CodeCorps.Analytics.SegmentTraitsBuilder.build()

assert_received({:track, ^invitee_id, "Claimed User Invite", ^traits})
end

test "supports claiming a user invite to a project if specified by an id parameter", %{
conn: conn
} do
project = insert(:project)
%{id: invite_id, email: email} = invite = insert(:user_invite, role: "contributor", project: project)

%{id: invite_id, email: email} =
invite = insert(:user_invite, role: "contributor", project: project)

attrs =
@valid_attrs
|> Map.merge(%{email: email, invite_id: invite_id, password: "password"})
Expand Down Expand Up @@ -230,7 +260,7 @@ defmodule CodeCorpsWeb.UserControllerTest do
|> authenticate(user)
|> put(path, params)

id = json_response(conn, 200)["data"]["id"] |> String.to_integer
id = json_response(conn, 200)["data"]["id"] |> String.to_integer()
assert_received {:identify, ^id, %{email: "original@mail.com"}}
assert_received {:track, ^id, "Updated Profile", %{}}
end
Expand Down Expand Up @@ -274,24 +304,27 @@ defmodule CodeCorpsWeb.UserControllerTest do
"relationships" => @relationships
}
}

conn =
conn
|> authenticate(user)
|> put(path, params)

json = json_response(conn, 422)
json = json_response(conn, 422)
assert json["errors"] != %{}
end

test "transitions from one state to the next", %{conn: conn} do
user = insert(:user)
conn = put authenticate(conn, user), user_path(conn, :update, user), %{
"data" => %{
"type" => "user",
"id" => user.id,
"attributes" => %{"password" => "password", "state_transition" => "edit_profile"}
}
}

conn =
put(authenticate(conn, user), user_path(conn, :update, user), %{
"data" => %{
"type" => "user",
"id" => user.id,
"attributes" => %{"password" => "password", "state_transition" => "edit_profile"}
}
})

%{"data" => %{"id" => id}} = json_response(conn, 200)
user = Repo.get(User, id)
Expand All @@ -306,24 +339,32 @@ defmodule CodeCorpsWeb.UserControllerTest do
@attrs %{"code" => "foo", "state" => "bar"}

@tag :authenticated
test "return the user when current user connects successfully", %{conn: conn, current_user: current_user} do
test "return the user when current user connects successfully", %{
conn: conn,
current_user: current_user
} do
path = user_path(conn, :github_oauth)

json = conn |> post(path, @attrs) |> json_response(200)

assert json["data"]["id"] |> String.to_integer == current_user.id
assert json["data"]["id"] |> String.to_integer() == current_user.id
assert json["data"]["attributes"]["github-id"]
end

@tag :authenticated
test "tracks event on segment when current user connects successfully", %{conn: conn, current_user: %{id: id}} do
test "tracks event on segment when current user connects successfully", %{
conn: conn,
current_user: %{id: id}
} do
path = user_path(conn, :github_oauth)

assert conn |> post(path, @attrs) |> json_response(200)

expected_data =
User
|> Repo.get(id)
|> CodeCorps.Analytics.SegmentTraitsBuilder.build
|> CodeCorps.Analytics.SegmentTraitsBuilder.build()

assert_received {:track, ^id, "Connected to GitHub", ^expected_data}
end

Expand All @@ -336,30 +377,30 @@ defmodule CodeCorpsWeb.UserControllerTest do
test "renders 500 if there's a GitHub API error", %{conn: conn} do
path = user_path(conn, :github_oauth)

with_mock_api(CodeCorps.GitHub.FailureAPI) do
with_mock_api CodeCorps.GitHub.FailureAPI do
assert conn |> post(path, @attrs) |> json_response(500)
end
end
end

describe "email_available" do
test "returns valid and available when email is valid and available", %{conn: conn} do
resp = get conn, user_path(conn, :email_available, %{email: "available@mail.com"})
resp = get(conn, user_path(conn, :email_available, %{email: "available@mail.com"}))
json = json_response(resp, 200)
assert json["available"]
assert json["valid"]
end

test "returns valid but inavailable when email is valid but taken", %{conn: conn} do
insert(:user, email: "used@mail.com")
resp = get conn, user_path(conn, :email_available, %{email: "used@mail.com"})
resp = get(conn, user_path(conn, :email_available, %{email: "used@mail.com"}))
json = json_response(resp, 200)
refute json["available"]
assert json["valid"]
end

test "returns as available but invalid when email is invalid", %{conn: conn} do
resp = get conn, user_path(conn, :email_available, %{email: "not_an_email"})
resp = get(conn, user_path(conn, :email_available, %{email: "not_an_email"}))
json = json_response(resp, 200)
assert json["available"]
refute json["valid"]
Expand All @@ -368,22 +409,22 @@ defmodule CodeCorpsWeb.UserControllerTest do

describe "username_available" do
test "returns as valid and available when username is valid and available", %{conn: conn} do
resp = get conn, user_path(conn, :username_available, %{username: "available"})
resp = get(conn, user_path(conn, :username_available, %{username: "available"}))
json = json_response(resp, 200)
assert json["available"]
assert json["valid"]
end

test "returns as valid, but inavailable when username is valid but taken", %{conn: conn} do
insert(:user, username: "used")
resp = get conn, user_path(conn, :username_available, %{username: "used"})
resp = get(conn, user_path(conn, :username_available, %{username: "used"}))
json = json_response(resp, 200)
refute json["available"]
assert json["valid"]
end

test "returns available but invalid when username is invalid", %{conn: conn} do
resp = get conn, user_path(conn, :username_available, %{username: ""})
resp = get(conn, user_path(conn, :username_available, %{username: ""}))
json = json_response(resp, 200)
assert json["available"]
refute json["valid"]
Expand Down

0 comments on commit 561dfe2

Please sign in to comment.