mirror of
https://github.com/plausible/analytics.git
synced 2024-12-25 18:48:06 +03:00
6a2d7fc0f5
* Merge `Plugins.API.Router` into main one In order to get grafana metrics reported See: https://github.com/akoutmos/prom_ex/issues/224 * Format
695 lines
21 KiB
Elixir
695 lines
21 KiB
Elixir
defmodule PlausibleWeb.Plugins.API.Controllers.GoalsTest do
|
|
use PlausibleWeb.PluginsAPICase, async: true
|
|
alias PlausibleWeb.Plugins.API.Schemas
|
|
|
|
describe "examples" do
|
|
test "Goal.CreateRequest.Revenue" do
|
|
assert_schema(
|
|
Schemas.Goal.CreateRequest.Revenue.schema().example,
|
|
"Goal.CreateRequest.Revenue",
|
|
spec()
|
|
)
|
|
end
|
|
|
|
test "Goal.CreateRequest.Pageview" do
|
|
assert_schema(
|
|
Schemas.Goal.CreateRequest.Pageview.schema().example,
|
|
"Goal.CreateRequest.Pageview",
|
|
spec()
|
|
)
|
|
end
|
|
|
|
test "Goal.CreateRequest.CustomEvent" do
|
|
assert_schema(
|
|
Schemas.Goal.CreateRequest.CustomEvent.schema().example,
|
|
"Goal.CreateRequest.CustomEvent",
|
|
spec()
|
|
)
|
|
end
|
|
end
|
|
|
|
describe "unauthorized calls" do
|
|
for {method, url} <- [
|
|
{:get, Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :index)},
|
|
{:get, Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :get, 1)},
|
|
{:put, Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create, %{})},
|
|
{:delete, Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :delete, 1)},
|
|
{:delete, Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :delete_bulk, %{})}
|
|
] do
|
|
test "unauthorized call: #{method} #{url}", %{conn: conn} do
|
|
conn
|
|
|> unquote(method)(unquote(url))
|
|
|> json_response(401)
|
|
|> assert_schema("UnauthorizedError", spec())
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "business tier" do
|
|
@tag :full_build_only
|
|
test "fails on revenue goal creation attempt with insufficient plan", %{
|
|
site: site,
|
|
token: token,
|
|
conn: conn
|
|
} do
|
|
site = Plausible.Repo.preload(site, :owner)
|
|
insert(:growth_subscription, user: site.owner)
|
|
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
payload = %{
|
|
goal_type: "Goal.Revenue",
|
|
goal: %{event_name: "Purchase", currency: "EUR"}
|
|
}
|
|
|
|
assert_request_schema(payload, "Goal.CreateRequest.Revenue", spec())
|
|
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> put(url, payload)
|
|
|> json_response(402)
|
|
|> assert_schema("PaymentRequiredError", spec())
|
|
end
|
|
|
|
@tag :full_build_only
|
|
test "fails on bulk revenue goal creation attempt with insufficient plan", %{
|
|
site: site,
|
|
token: token,
|
|
conn: conn
|
|
} do
|
|
site = Plausible.Repo.preload(site, :owner)
|
|
insert(:growth_subscription, user: site.owner)
|
|
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
payload = %{
|
|
goals: [
|
|
%{
|
|
goal_type: "Goal.CustomEvent",
|
|
goal: %{event_name: "Signup"}
|
|
},
|
|
%{
|
|
goal_type: "Goal.Revenue",
|
|
goal: %{event_name: "Purchase", currency: "EUR"}
|
|
},
|
|
%{
|
|
goal_type: "Goal.Pageview",
|
|
goal: %{path: "/checkout"}
|
|
}
|
|
]
|
|
}
|
|
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> put(url, payload)
|
|
|> json_response(402)
|
|
|> assert_schema("PaymentRequiredError", spec())
|
|
end
|
|
end
|
|
|
|
describe "put /goals - create a single goal" do
|
|
test "validates input according to the schema", %{conn: conn, token: token, site: site} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> put(url, %{goal_type: "Goal.SomeTypo", goal: %{event_name: "Signup"}})
|
|
|> json_response(422)
|
|
|> assert_schema("UnprocessableEntityError", spec())
|
|
end
|
|
|
|
test "creates a custom event goal", %{conn: conn, token: token, site: site} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
payload = %{goal_type: "Goal.CustomEvent", goal: %{event_name: "Signup"}}
|
|
|
|
assert_request_schema(payload, "Goal.CreateRequest.CustomEvent", spec())
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> put(url, payload)
|
|
|
|
resp =
|
|
conn
|
|
|> json_response(201)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
resp.goals
|
|
|> List.first()
|
|
|> assert_schema("Goal.CustomEvent", spec())
|
|
|
|
[location] = get_resp_header(conn, "location")
|
|
|
|
assert location ==
|
|
Routes.plugins_api_goals_url(
|
|
PlausibleWeb.Endpoint,
|
|
:get,
|
|
List.first(resp.goals).goal.id
|
|
)
|
|
|
|
assert [%{event_name: "Signup"}] = Plausible.Goals.for_site(site)
|
|
end
|
|
|
|
@tag :full_build_only
|
|
test "creates a revenue goal", %{conn: conn, token: token, site: site} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
payload = %{
|
|
goal_type: "Goal.Revenue",
|
|
goal: %{event_name: "Purchase", currency: "EUR"}
|
|
}
|
|
|
|
assert_request_schema(payload, "Goal.CreateRequest.Revenue", spec())
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> put(url, payload)
|
|
|
|
resp =
|
|
conn
|
|
|> json_response(201)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
resp.goals
|
|
|> List.first()
|
|
|> assert_schema("Goal.Revenue", spec())
|
|
|
|
[location] = get_resp_header(conn, "location")
|
|
|
|
assert location ==
|
|
Routes.plugins_api_goals_url(
|
|
PlausibleWeb.Endpoint,
|
|
:get,
|
|
List.first(resp.goals).goal.id
|
|
)
|
|
|
|
assert [%{event_name: "Purchase", currency: :EUR}] = Plausible.Goals.for_site(site)
|
|
end
|
|
|
|
@tag :full_build_only
|
|
test "fails to create a revenue goal with unknown currency", %{
|
|
conn: conn,
|
|
token: token,
|
|
site: site
|
|
} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
payload = %{
|
|
goal_type: "Goal.Revenue",
|
|
goal: %{event_name: "Purchase", currency: "DFJKHJESFHYU"}
|
|
}
|
|
|
|
assert_request_schema(payload, "Goal.CreateRequest.Revenue", spec())
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> put(url, payload)
|
|
|
|
resp =
|
|
conn
|
|
|> json_response(422)
|
|
|> assert_schema("UnprocessableEntityError", spec())
|
|
|
|
assert [%{detail: "currency: is invalid"}] = resp.errors
|
|
end
|
|
|
|
@tag :full_build_only
|
|
test "edge case - revenue goal exists under the same name and different currency", %{
|
|
conn: conn,
|
|
token: token,
|
|
site: site
|
|
} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
{:ok, _} = Plausible.Goals.create(site, %{"event_name" => "Purchase", "currency" => "USD"})
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> put(url, %{goal_type: "Goal.Revenue", goal: %{event_name: "Purchase", currency: "EUR"}})
|
|
|
|
resp =
|
|
conn
|
|
|> json_response(422)
|
|
|> assert_schema("UnprocessableEntityError", spec())
|
|
|
|
assert [%{detail: "event_name: 'Purchase' (with currency: USD) has already been taken"}] =
|
|
resp.errors
|
|
end
|
|
|
|
test "creates a pageview goal", %{conn: conn, token: token, site: site} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
payload = %{goal_type: "Goal.Pageview", goal: %{path: "/checkout"}}
|
|
assert_request_schema(payload, "Goal.CreateRequest.Pageview", spec())
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> put(url, payload)
|
|
|
|
resp =
|
|
conn
|
|
|> json_response(201)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
resp.goals
|
|
|> List.first()
|
|
|> assert_schema("Goal.Pageview", spec())
|
|
|
|
[location] = get_resp_header(conn, "location")
|
|
|
|
assert location ==
|
|
Routes.plugins_api_goals_url(
|
|
PlausibleWeb.Endpoint,
|
|
:get,
|
|
List.first(resp.goals).goal.id
|
|
)
|
|
|
|
assert [%{page_path: "/checkout"}] = Plausible.Goals.for_site(site)
|
|
end
|
|
|
|
test "is idempotent", %{conn: conn, token: token, site: site} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
initial_conn =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|
|
resp1 =
|
|
initial_conn
|
|
|> put(url, %{goal_type: "Goal.Pageview", goal: %{path: "/checkout"}})
|
|
|> json_response(201)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
resp1.goals
|
|
|> List.first()
|
|
|> assert_schema("Goal.Pageview", spec())
|
|
|
|
assert initial_conn
|
|
|> put(url, %{goal_type: "Goal.Pageview", goal: %{path: "/checkout"}})
|
|
|> json_response(201)
|
|
|> assert_schema("Goal.ListResponse", spec()) == resp1
|
|
end
|
|
end
|
|
|
|
describe "put /goals - bulk creation" do
|
|
@tag :full_build_only
|
|
test "creates a goal of each type", %{conn: conn, token: token, site: site} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
payload = %{
|
|
goals: [
|
|
%{
|
|
goal_type: "Goal.CustomEvent",
|
|
goal: %{event_name: "Signup"}
|
|
},
|
|
%{
|
|
goal_type: "Goal.Revenue",
|
|
goal: %{event_name: "Purchase", currency: "EUR"}
|
|
},
|
|
%{
|
|
goal_type: "Goal.Pageview",
|
|
goal: %{path: "/checkout"}
|
|
}
|
|
]
|
|
}
|
|
|
|
assert_request_schema(payload, "Goal.CreateRequest.BulkGetOrCreate", spec())
|
|
|
|
conn =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> put(url, payload)
|
|
|
|
resp =
|
|
conn
|
|
|> json_response(201)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
[l1, l2, l3] = get_resp_header(conn, "location")
|
|
|
|
assert l1 ==
|
|
Routes.plugins_api_goals_url(
|
|
PlausibleWeb.Endpoint,
|
|
:get,
|
|
Enum.at(resp.goals, 0).goal.id
|
|
)
|
|
|
|
assert l2 ==
|
|
Routes.plugins_api_goals_url(
|
|
PlausibleWeb.Endpoint,
|
|
:get,
|
|
Enum.at(resp.goals, 1).goal.id
|
|
)
|
|
|
|
assert l3 ==
|
|
Routes.plugins_api_goals_url(
|
|
PlausibleWeb.Endpoint,
|
|
:get,
|
|
Enum.at(resp.goals, 2).goal.id
|
|
)
|
|
|
|
assert Enum.count(resp.goals) == 3
|
|
|
|
assert [
|
|
%{page_path: "/checkout"},
|
|
%{event_name: "Purchase", currency: :EUR},
|
|
%{event_name: "Signup"}
|
|
] = Plausible.Goals.for_site(site)
|
|
end
|
|
|
|
test "no more than 8 goals can be created in bulk", %{conn: conn, token: token, site: site} do
|
|
# if this test fails due to implementation change, consider what to do with the pagination meta
|
|
# object returned in the response and also revise how funnels are created based on a list of goals
|
|
# - the funnels creation endpoint will likely reuse this schema's constraints
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
payload =
|
|
Enum.map(1..9, fn i ->
|
|
%{goal_type: "Goal.CustomEvent", goal: %{event_name: "Bulk Goal ##{i}"}}
|
|
end)
|
|
|
|
resp =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> put(url, %{
|
|
goals: payload
|
|
})
|
|
|> json_response(422)
|
|
|> assert_schema("UnprocessableEntityError", spec())
|
|
|
|
assert %Schemas.Error{
|
|
detail: "Array length 9 is larger than maxItems: 8"
|
|
} in resp.errors
|
|
end
|
|
|
|
@tag :full_build_only
|
|
test "is idempotent", %{conn: conn, token: token, site: site} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
initial_conn =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|
|
payload = [
|
|
%{
|
|
goal_type: "Goal.CustomEvent",
|
|
goal: %{event_name: "Signup"}
|
|
},
|
|
%{
|
|
goal_type: "Goal.Revenue",
|
|
goal: %{event_name: "Purchase", currency: "EUR"}
|
|
},
|
|
%{
|
|
goal_type: "Goal.Pageview",
|
|
goal: %{path: "/checkout"}
|
|
}
|
|
]
|
|
|
|
initial_conn
|
|
|> put(url, %{goals: payload})
|
|
|> json_response(201)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
initial_conn
|
|
|> put(url, %{goals: payload})
|
|
|> json_response(201)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
end
|
|
|
|
@tag :full_build_only
|
|
test "edge case - revenue goals exist under the same name and different currency", %{
|
|
conn: conn,
|
|
token: token,
|
|
site: site
|
|
} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :create)
|
|
|
|
initial_conn =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|
|
payload1 = [%{goal_type: "Goal.Revenue", goal: %{event_name: "Purchase", currency: "EUR"}}]
|
|
payload2 = [%{goal_type: "Goal.Revenue", goal: %{event_name: "Purchase", currency: "USD"}}]
|
|
|
|
initial_conn
|
|
|> put(url, %{goals: payload1})
|
|
|> json_response(201)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
resp =
|
|
initial_conn
|
|
|> put(url, %{goals: payload2})
|
|
|> json_response(422)
|
|
|> assert_schema("UnprocessableEntityError", spec())
|
|
|
|
assert [%{detail: "event_name: 'Purchase' (with currency: EUR) has already been taken"}] =
|
|
resp.errors
|
|
end
|
|
end
|
|
|
|
describe "get /goals/:id" do
|
|
test "validates input out of the box", %{conn: conn, token: token, site: site} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :get, "hello")
|
|
|
|
resp =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> get(url)
|
|
|> json_response(422)
|
|
|> assert_schema("UnprocessableEntityError", spec())
|
|
|
|
assert %{errors: [%{detail: "Invalid integer. Got: string"}]} = resp
|
|
end
|
|
|
|
@tag :full_build_only
|
|
test "retrieves revenue goal by ID", %{conn: conn, site: site, token: token} do
|
|
{:ok, goal} =
|
|
Plausible.Goals.create(site, %{"event_name" => "Purchase", "currency" => "EUR"})
|
|
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :get, goal.id)
|
|
|
|
resp =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> get(url)
|
|
|> json_response(200)
|
|
|> assert_schema("Goal", spec())
|
|
|> assert_schema("Goal.Revenue", spec())
|
|
|
|
assert resp.goal.id == goal.id
|
|
assert resp.goal_type == "Goal.Revenue"
|
|
assert resp.goal.display_name == "Purchase (EUR)"
|
|
end
|
|
|
|
test "retrieves pageview goal by ID", %{conn: conn, site: site, token: token} do
|
|
{:ok, goal} = Plausible.Goals.create(site, %{"page_path" => "/checkout"})
|
|
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :get, goal.id)
|
|
|
|
resp =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> get(url)
|
|
|> json_response(200)
|
|
|> assert_schema("Goal", spec())
|
|
|> assert_schema("Goal.Pageview", spec())
|
|
|
|
assert resp.goal.id == goal.id
|
|
assert resp.goal_type == "Goal.Pageview"
|
|
assert resp.goal.display_name == "Visit /checkout"
|
|
end
|
|
|
|
test "retrieves custom event goal by ID", %{conn: conn, site: site, token: token} do
|
|
{:ok, goal} = Plausible.Goals.create(site, %{"event_name" => "Signup"})
|
|
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :get, goal.id)
|
|
|
|
resp =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> get(url)
|
|
|> json_response(200)
|
|
|> assert_schema("Goal", spec())
|
|
|> assert_schema("Goal.CustomEvent", spec())
|
|
|
|
assert resp.goal.id == goal.id
|
|
assert resp.goal_type == "Goal.CustomEvent"
|
|
assert resp.goal.display_name == "Signup"
|
|
end
|
|
end
|
|
|
|
describe "get /goals" do
|
|
test "returns an empty goals list if there's none", %{
|
|
conn: conn,
|
|
token: token,
|
|
site: site
|
|
} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :index)
|
|
|
|
resp =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> get(url)
|
|
|> json_response(200)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
assert resp.goals == []
|
|
assert resp.meta.pagination.has_next_page == false
|
|
assert resp.meta.pagination.has_prev_page == false
|
|
assert resp.meta.pagination.links == %{}
|
|
end
|
|
|
|
@tag :full_build_only
|
|
test "returns a list of goals of each possible goal type", %{
|
|
conn: conn,
|
|
site: site,
|
|
token: token
|
|
} do
|
|
{:ok, g1} = Plausible.Goals.create(site, %{"event_name" => "Signup"})
|
|
{:ok, g2} = Plausible.Goals.create(site, %{"event_name" => "Purchase", "currency" => "EUR"})
|
|
{:ok, g3} = Plausible.Goals.create(site, %{"page_path" => "/checkout"})
|
|
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :index)
|
|
|
|
resp =
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> get(url)
|
|
|> json_response(200)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
assert [checkout, purchase, signup] = resp.goals
|
|
assert checkout.goal.display_name == "Visit /checkout"
|
|
assert checkout.goal.path == "/checkout"
|
|
assert checkout.goal.id == g3.id
|
|
assert checkout.goal_type == "Goal.Pageview"
|
|
|
|
assert purchase.goal.display_name == "Purchase (EUR)"
|
|
assert purchase.goal.currency == "EUR"
|
|
assert purchase.goal.event_name == "Purchase"
|
|
assert purchase.goal.id == g2.id
|
|
assert purchase.goal_type == "Goal.Revenue"
|
|
|
|
assert signup.goal.display_name == "Signup"
|
|
assert signup.goal.event_name == "Signup"
|
|
assert signup.goal.id == g1.id
|
|
assert signup.goal_type == "Goal.CustomEvent"
|
|
end
|
|
|
|
test "returns a list of goals with pagination", %{conn: conn, site: site, token: token} do
|
|
for i <- 1..5 do
|
|
insert(:goal, site: site, event_name: "Goal #{i}")
|
|
end
|
|
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :index, limit: 2)
|
|
|
|
initial_conn = authenticate(conn, site.domain, token)
|
|
|
|
page1 =
|
|
initial_conn
|
|
|> get(url)
|
|
|> json_response(200)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
assert [%{goal: %{event_name: "Goal 5"}}, %{goal: %{event_name: "Goal 4"}}] = page1.goals
|
|
assert page1.meta.pagination.has_next_page == true
|
|
assert page1.meta.pagination.has_prev_page == false
|
|
assert page1.meta.pagination.links.next
|
|
refute page1.meta.pagination.links[:prev]
|
|
|
|
page2 =
|
|
initial_conn
|
|
|> get(page1.meta.pagination.links.next.url)
|
|
|> json_response(200)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
|
|
assert [%{goal: %{event_name: "Goal 3"}}, %{goal: %{event_name: "Goal 2"}}] = page2.goals
|
|
|
|
assert page2.meta.pagination.has_next_page == true
|
|
assert page2.meta.pagination.has_prev_page == true
|
|
assert page2.meta.pagination.links.next
|
|
assert page2.meta.pagination.links.prev
|
|
|
|
assert ^page1 =
|
|
initial_conn
|
|
|> get(page2.meta.pagination.links.prev.url)
|
|
|> json_response(200)
|
|
|> assert_schema("Goal.ListResponse", spec())
|
|
end
|
|
end
|
|
|
|
describe "delete /goals/:id" do
|
|
test "deletes goal by id", %{conn: conn, site: site, token: token} do
|
|
{:ok, %{id: goal_id}} =
|
|
Plausible.Goals.create(site, %{"event_name" => "Purchase", "currency" => "USD"})
|
|
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :delete, goal_id)
|
|
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> delete(url)
|
|
|> response(204)
|
|
|
|
refute Plausible.Repo.exists?(Plausible.Goal)
|
|
end
|
|
|
|
test "is idempotent", %{conn: conn, site: site, token: token} do
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :delete, 666)
|
|
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> delete(url)
|
|
|> response(204)
|
|
end
|
|
end
|
|
|
|
describe "delete - bulk" do
|
|
test "delete multiple goals", %{conn: conn, site: site, token: token} do
|
|
{:ok, g1} =
|
|
Plausible.Goals.create(site, %{"event_name" => "Purchase", "currency" => "USD"})
|
|
|
|
{:ok, g2} =
|
|
Plausible.Goals.create(site, %{"event_name" => "Signup"})
|
|
|
|
{:ok, g3} =
|
|
Plausible.Goals.create(site, %{"page_path" => "/home"})
|
|
|
|
url = Routes.plugins_api_goals_url(PlausibleWeb.Endpoint, :delete_bulk)
|
|
|
|
payload = %{
|
|
goal_ids: [
|
|
g1.id,
|
|
g2.id,
|
|
g3.id
|
|
]
|
|
}
|
|
|
|
conn
|
|
|> authenticate(site.domain, token)
|
|
|> put_req_header("content-type", "application/json")
|
|
|> delete(url, payload)
|
|
|> response(204)
|
|
|
|
refute Plausible.Repo.exists?(Plausible.Goal)
|
|
end
|
|
end
|
|
end
|