mirror of
https://github.com/plausible/analytics.git
synced 2024-12-22 17:11:36 +03:00
Google APIs integration improvements (#2358)
* Make TestUtils module available in all tests * Add macros patching the application env in tests Unfortunately a lot of existing functionality relies on certain application env setup. This isn't ideal because the app config is a shared state that prevents us from running the tests in parallel. Those macros encapsulate setting up new env for test purposes and make sure the changes are reverted when the test finishes. * Allow passing request opts to HTTPClient.post/4 We need this to swap custom request building in Google Analytics import. * Unify errors when listing sites * React: propagate backend error messages if available * React: catch API errors in Search Terms component * Propagate google API errors on referrer drilldown * Handle verified properties errors in SC settings * Add missing tests for SC settings controller * Unify errors for fetching search analytics queries (list stats) * Unify errors refreshing Google Auth Token * Test fetch_stats/3 errors and replace Double with Mox * Fixup makrup * s/class/className * Simplify Search Terms display in case of errors * Fix warnings
This commit is contained in:
parent
93bb62ef27
commit
0fa6b688af
@ -4,9 +4,10 @@ let abortController = new AbortController()
|
||||
let SHARED_LINK_AUTH = null
|
||||
|
||||
class ApiError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = "ApiError";
|
||||
constructor(message, payload) {
|
||||
super(message)
|
||||
this.name = "ApiError"
|
||||
this.payload = payload
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,7 +57,7 @@ export function get(url, query={}, ...extraQuery) {
|
||||
.then( response => {
|
||||
if (!response.ok) {
|
||||
return response.json().then((msg) => {
|
||||
throw new ApiError(msg.error)
|
||||
throw new ApiError(msg.error, msg)
|
||||
})
|
||||
}
|
||||
return response.json()
|
||||
|
@ -30,7 +30,11 @@ export default class SearchTerms extends React.Component {
|
||||
searchTerms: res.search_terms || [],
|
||||
notConfigured: res.not_configured,
|
||||
isAdmin: res.is_admin
|
||||
}))
|
||||
})).catch((error) =>
|
||||
{
|
||||
this.setState({ loading: false, searchTerms: [], notConfigured: true, error: true, isAdmin: error.payload.is_admin })
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
renderSearchTerm(term) {
|
||||
@ -67,8 +71,10 @@ export default class SearchTerms extends React.Component {
|
||||
return (
|
||||
<div className="text-center text-gray-700 dark:text-gray-300 text-sm mt-20">
|
||||
<RocketIcon />
|
||||
<div>The site is not connected to Google Search Keywords</div>
|
||||
<div>Cannot show search terms</div>
|
||||
<div>
|
||||
This site is not connected to Search Console so we cannot show the search phrases.
|
||||
{this.state.isAdmin && this.state.error && <><br/><br/><p>Please click below to connect your Search Console account.</p></>}
|
||||
</div>
|
||||
{this.state.isAdmin && <a href={`/${encodeURIComponent(this.props.site.domain)}/settings/search-console`} className="button mt-4">Connect with Google</a> }
|
||||
</div>
|
||||
)
|
||||
|
@ -182,9 +182,8 @@ defmodule Plausible.Google.Api do
|
||||
buffer_pid = Keyword.get(opts, :buffer)
|
||||
attempt = Keyword.get(opts, :attempt, 1)
|
||||
sleep_time = Keyword.get(opts, :sleep_time, 1000)
|
||||
http_client = Keyword.get(opts, :http_client, Finch)
|
||||
|
||||
case HTTP.get_report(http_client, report_request) do
|
||||
case HTTP.get_report(report_request) do
|
||||
{:ok, {rows, next_page_token}} ->
|
||||
records = Plausible.Imported.from_google_analytics(rows, site.id, report_request.dataset)
|
||||
:ok = Plausible.Google.Buffer.insert_many(buffer_pid, report_request.dataset, records)
|
||||
|
@ -2,82 +2,65 @@ defmodule Plausible.Google.HTTP do
|
||||
require Logger
|
||||
alias Plausible.HTTPClient
|
||||
|
||||
@spec get_report(module(), Plausible.Google.ReportRequest.t()) ::
|
||||
@spec get_report(Plausible.Google.ReportRequest.t()) ::
|
||||
{:ok, {[map()], String.t() | nil}} | {:error, any()}
|
||||
def get_report(http_client, %Plausible.Google.ReportRequest{} = report_request) do
|
||||
params =
|
||||
Jason.encode!(%{
|
||||
reportRequests: [
|
||||
%{
|
||||
viewId: report_request.view_id,
|
||||
dateRanges: [
|
||||
%{
|
||||
startDate: report_request.date_range.first,
|
||||
endDate: report_request.date_range.last
|
||||
}
|
||||
],
|
||||
dimensions: Enum.map(report_request.dimensions, &%{name: &1, histogramBuckets: []}),
|
||||
metrics: Enum.map(report_request.metrics, &%{expression: &1}),
|
||||
hideTotals: true,
|
||||
hideValueRanges: true,
|
||||
orderBys: [%{fieldName: "ga:date", sortOrder: "DESCENDING"}],
|
||||
pageSize: report_request.page_size,
|
||||
pageToken: report_request.page_token
|
||||
}
|
||||
]
|
||||
})
|
||||
def get_report(%Plausible.Google.ReportRequest{} = report_request) do
|
||||
params = %{
|
||||
reportRequests: [
|
||||
%{
|
||||
viewId: report_request.view_id,
|
||||
dateRanges: [
|
||||
%{
|
||||
startDate: report_request.date_range.first,
|
||||
endDate: report_request.date_range.last
|
||||
}
|
||||
],
|
||||
dimensions: Enum.map(report_request.dimensions, &%{name: &1, histogramBuckets: []}),
|
||||
metrics: Enum.map(report_request.metrics, &%{expression: &1}),
|
||||
hideTotals: true,
|
||||
hideValueRanges: true,
|
||||
orderBys: [%{fieldName: "ga:date", sortOrder: "DESCENDING"}],
|
||||
pageSize: report_request.page_size,
|
||||
pageToken: report_request.page_token
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
response =
|
||||
:post
|
||||
|> Finch.build(
|
||||
HTTPClient.impl().post(
|
||||
"#{reporting_api_url()}/v4/reports:batchGet",
|
||||
[{"Authorization", "Bearer #{report_request.access_token}"}],
|
||||
params
|
||||
params,
|
||||
receive_timeout: 60_000
|
||||
)
|
||||
|> http_client.request(Plausible.Finch, receive_timeout: 60_000)
|
||||
|
||||
with {:ok, %{status: 200, body: body}} <- response,
|
||||
with {:ok, %{body: body}} <- response,
|
||||
{:ok, report} <- parse_report_from_response(body),
|
||||
token <- Map.get(report, "nextPageToken"),
|
||||
{:ok, report} <- convert_to_maps(report) do
|
||||
{:ok, {report, token}}
|
||||
else
|
||||
{:ok, %{status: _non_http_200, body: _body} = response} ->
|
||||
report_failed_request_to_sentry(response)
|
||||
{:error, %{reason: %{status: status, body: body}}} ->
|
||||
Sentry.Context.set_extra_context(%{ga_response: %{body: body, status: status}})
|
||||
{:error, :request_failed}
|
||||
|
||||
{:error, cause} ->
|
||||
{:error, cause}
|
||||
{:error, _} ->
|
||||
{:error, :request_failed}
|
||||
end
|
||||
end
|
||||
|
||||
defp report_failed_request_to_sentry(%{status: status, body: body}) do
|
||||
case Jason.decode(body) do
|
||||
{:ok, %{} = body} ->
|
||||
Sentry.Context.set_extra_context(%{ga_response: %{body: body, status: status}})
|
||||
|
||||
_error ->
|
||||
Sentry.Context.set_extra_context(%{ga_response: %{body: body, status: status}})
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_report_from_response(raw_body) do
|
||||
with {:ok, map} <- Jason.decode(raw_body),
|
||||
%{"reports" => [report | _]} <- map do
|
||||
defp parse_report_from_response(body) do
|
||||
with %{"reports" => [report | _]} <- body do
|
||||
{:ok, report}
|
||||
else
|
||||
{:error, cause} ->
|
||||
Logger.error("Google Analytics: Failed to parse JSON. Reason: #{inspect(cause)}")
|
||||
Sentry.Context.set_extra_context(%{google_analytics_response: raw_body})
|
||||
{:error, cause}
|
||||
_ ->
|
||||
Sentry.Context.set_extra_context(%{google_analytics_response: body})
|
||||
|
||||
%{} = response ->
|
||||
Logger.error(
|
||||
"Google Analytics: Failed to find report in response. Reason: #{inspect(response)}"
|
||||
"Google Analytics: Failed to find report in response. Reason: #{inspect(body)}"
|
||||
)
|
||||
|
||||
Sentry.Context.set_extra_context(%{google_analytics_response: response})
|
||||
{:error, {:invalid_response, response}}
|
||||
{:error, {:invalid_response, body}}
|
||||
end
|
||||
end
|
||||
|
||||
@ -114,13 +97,19 @@ defmodule Plausible.Google.HTTP do
|
||||
url = "#{api_url()}/webmasters/v3/sites"
|
||||
headers = [{"Content-Type", "application/json"}, {"Authorization", "Bearer #{access_token}"}]
|
||||
|
||||
case HTTPClient.get(url, headers) do
|
||||
case HTTPClient.impl().get(url, headers) do
|
||||
{:ok, %{body: body}} ->
|
||||
{:ok, body}
|
||||
|
||||
{:error, reason} = e ->
|
||||
{:error, %{reason: %{status: s}}} when s in [401, 403] ->
|
||||
{:error, "google_auth_error"}
|
||||
|
||||
{:error, %{reason: %{body: %{"error" => error}}}} ->
|
||||
{:error, error}
|
||||
|
||||
{:error, reason} ->
|
||||
Logger.error("Google Analytics: failed to list sites: #{inspect(reason)}")
|
||||
e
|
||||
{:error, "failed_to_list_sites"}
|
||||
end
|
||||
end
|
||||
|
||||
@ -182,25 +171,20 @@ defmodule Plausible.Google.HTTP do
|
||||
url = "#{api_url()}/webmasters/v3/sites/#{property}/searchAnalytics/query"
|
||||
headers = [{"Authorization", "Bearer #{access_token}"}]
|
||||
|
||||
case HTTPClient.post(url, headers, params) do
|
||||
case HTTPClient.impl().post(url, headers, params) do
|
||||
{:ok, %Finch.Response{body: body, status: 200}} ->
|
||||
{:ok, body}
|
||||
|
||||
{:error, %{reason: %Finch.Response{body: body, status: 401}}} ->
|
||||
Sentry.capture_message("Error fetching Google queries", extra: %{body: inspect(body)})
|
||||
{:error, :invalid_credentials}
|
||||
{:error, %{reason: %Finch.Response{body: _body, status: status}}}
|
||||
when status in [401, 403] ->
|
||||
{:error, "google_auth_error"}
|
||||
|
||||
{:error, %{reason: %Finch.Response{body: body, status: 403}}} ->
|
||||
Sentry.capture_message("Error fetching Google queries", extra: %{body: inspect(body)})
|
||||
{:error, get_in(body, ["error", "message"])}
|
||||
{:error, %{reason: %{body: %{"error" => error}}}} ->
|
||||
{:error, error}
|
||||
|
||||
{:error, %{reason: %Finch.Response{body: body}}} ->
|
||||
Sentry.capture_message("Error fetching Google queries", extra: %{body: inspect(body)})
|
||||
{:error, :unknown}
|
||||
|
||||
{:error, %{reason: _} = e} ->
|
||||
Sentry.capture_message("Error fetching Google queries", extra: %{error: inspect(e)})
|
||||
{:error, :unknown}
|
||||
{:error, reason} ->
|
||||
Logger.error("Google Analytics: failed to list stats: #{inspect(reason)}")
|
||||
{:error, "failed_to_list_stats"}
|
||||
end
|
||||
end
|
||||
|
||||
@ -223,14 +207,12 @@ defmodule Plausible.Google.HTTP do
|
||||
{:ok, %Finch.Response{body: body, status: 200}} ->
|
||||
{:ok, body}
|
||||
|
||||
{:error, %{reason: %Finch.Response{body: body, status: _non_http_200}}} ->
|
||||
body
|
||||
|> Map.get("error")
|
||||
|> then(&{:error, &1})
|
||||
{:error, %{reason: %Finch.Response{body: %{"error" => error}, status: _non_http_200}}} ->
|
||||
{:error, error}
|
||||
|
||||
{:error, %{reason: _} = e} ->
|
||||
Sentry.capture_message("Error fetching Google queries", extra: %{error: inspect(e)})
|
||||
{:error, :unknown}
|
||||
{:error, :unknown_error}
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -11,6 +11,7 @@ defmodule Plausible.HTTPClient.Non200Error do
|
||||
end
|
||||
|
||||
defmodule Plausible.HTTPClient.Interface do
|
||||
@type finch_request_opts() :: Keyword.t()
|
||||
@type url() :: Finch.Request.url()
|
||||
@type headers() :: Finch.Request.headers()
|
||||
@type params() :: Finch.Request.body() | map()
|
||||
@ -21,6 +22,7 @@ defmodule Plausible.HTTPClient.Interface do
|
||||
@callback get(url(), headers()) :: response()
|
||||
@callback get(url()) :: response()
|
||||
@callback post(url(), headers(), params()) :: response()
|
||||
@callback post(url(), headers(), params(), finch_request_opts()) :: response()
|
||||
end
|
||||
|
||||
defmodule Plausible.HTTPClient do
|
||||
@ -40,8 +42,8 @@ defmodule Plausible.HTTPClient do
|
||||
@behaviour Plausible.HTTPClient.Interface
|
||||
|
||||
@impl Plausible.HTTPClient.Interface
|
||||
def post(url, headers \\ [], params \\ nil) do
|
||||
call(:post, url, headers, params)
|
||||
def post(url, headers \\ [], params \\ nil, finch_req_opts \\ []) do
|
||||
call(:post, url, headers, params, finch_req_opts)
|
||||
end
|
||||
|
||||
@doc """
|
||||
@ -59,12 +61,12 @@ defmodule Plausible.HTTPClient do
|
||||
Application.get_env(:plausible, :http_impl, __MODULE__)
|
||||
end
|
||||
|
||||
defp call(method, url, headers, params) do
|
||||
defp call(method, url, headers, params, finch_req_opts \\ []) do
|
||||
{params, headers} = maybe_encode_params(params, headers)
|
||||
|
||||
method
|
||||
|> build_request(url, headers, params)
|
||||
|> do_request()
|
||||
|> do_request(finch_req_opts)
|
||||
|> maybe_decode_body()
|
||||
|> tag_error()
|
||||
end
|
||||
@ -73,8 +75,8 @@ defmodule Plausible.HTTPClient do
|
||||
Finch.build(method, url, headers, params)
|
||||
end
|
||||
|
||||
defp do_request(request) do
|
||||
Finch.request(request, Plausible.Finch)
|
||||
defp do_request(request, finch_req_opts) do
|
||||
Finch.request(request, Plausible.Finch, finch_req_opts)
|
||||
end
|
||||
|
||||
defp maybe_encode_params(params, headers) when is_binary(params) or is_nil(params) do
|
||||
@ -123,7 +125,7 @@ defmodule Plausible.HTTPClient do
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_decode_body(resp), do: resp
|
||||
defp maybe_decode_body(response), do: response
|
||||
|
||||
defp json?(headers) do
|
||||
found =
|
||||
|
@ -429,18 +429,24 @@ defmodule PlausibleWeb.Api.StatsController do
|
||||
|
||||
%{:visitors => %{value: total_visitors}} = Stats.aggregate(site, query, [:visitors])
|
||||
|
||||
user_id = get_session(conn, :current_user_id)
|
||||
is_admin = user_id && Plausible.Sites.has_admin_access?(user_id, site)
|
||||
|
||||
case search_terms do
|
||||
nil ->
|
||||
user_id = get_session(conn, :current_user_id)
|
||||
is_admin = user_id && Plausible.Sites.has_admin_access?(user_id, site)
|
||||
json(conn, %{not_configured: true, is_admin: is_admin, total_visitors: total_visitors})
|
||||
|
||||
{:ok, terms} ->
|
||||
json(conn, %{search_terms: terms, total_visitors: total_visitors})
|
||||
|
||||
{:error, e} ->
|
||||
put_status(conn, 500)
|
||||
|> json(%{error: e})
|
||||
{:error, _} ->
|
||||
conn
|
||||
|> put_status(502)
|
||||
|> json(%{
|
||||
not_configured: true,
|
||||
is_admin: is_admin,
|
||||
total_visitors: total_visitors
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -36,12 +36,24 @@
|
||||
<%= submit "Save", class: "button" %>
|
||||
<% end %>
|
||||
<% {:error, error} -> %>
|
||||
<p class="text-gray-700 dark:text-gray-300 mt-6">The following error happened when fetching your Google Search Console domains.</p>
|
||||
<p class="text-gray-700 dark:text-gray-300 mt-6">The following error happened when fetching your Google Search Console domains:</p>
|
||||
|
||||
<%= if error == "invalid_grant" do %>
|
||||
<p class="text-red-700 font-medium mt-3"><a href="https://plausible.io/docs/google-search-console-integration#i-get-the-invalid-grant-error">Invalid Grant error returned from Google. <span class="text-indigo-500">See here on how to fix it.</a></p>
|
||||
<% else %>
|
||||
<p class="text-red-700 font-medium mt-3">Something went wrong</p>
|
||||
<%= case error do %>
|
||||
<% "invalid_grant" -> %>
|
||||
<p class="text-red-700 font-medium mt-3">
|
||||
<a href="https://plausible.io/docs/google-search-console-integration#i-get-the-invalid-grant-error">
|
||||
Invalid Grant error returned from Google. <span class="text-indigo-500">See here on how to fix it</span>.
|
||||
</a>
|
||||
</p>
|
||||
<% "google_auth_error" -> %>
|
||||
<p class="text-red-700 font-medium mt-3">
|
||||
Your Search Console account hasn't been connected successfully. Please unlink your Google account and try linking it again.
|
||||
</p>
|
||||
|
||||
<% _ -> %>
|
||||
<p class="text-red-700 font-medium mt-3">
|
||||
Something went wrong, but looks temporary. If the problem persists, try re-linking your Google account.
|
||||
</p>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
|
@ -2,7 +2,6 @@ defmodule Plausible.BillingTest do
|
||||
use Plausible.DataCase
|
||||
use Bamboo.Test, shared: true
|
||||
alias Plausible.Billing
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "usage" do
|
||||
test "is 0 with no events" do
|
||||
|
@ -2,13 +2,16 @@ defmodule Plausible.Google.ApiTest do
|
||||
use Plausible.DataCase, async: true
|
||||
use ExVCR.Mock, adapter: ExVCR.Adapter.Finch
|
||||
alias Plausible.Google.Api
|
||||
import Plausible.TestUtils
|
||||
import Double
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Mox
|
||||
setup :verify_on_exit!
|
||||
|
||||
setup [:create_user, :create_new_site]
|
||||
|
||||
describe "fetch_and_persist/4" do
|
||||
@ok_response File.read!("fixture/ga_batch_report.json")
|
||||
@ok_response Jason.decode!(File.read!("fixture/ga_batch_report.json"))
|
||||
@no_report_response Jason.decode!(File.read!("fixture/ga_report_empty_rows.json"))
|
||||
|
||||
setup do
|
||||
{:ok, pid} = Plausible.Google.Buffer.start_link()
|
||||
@ -16,12 +19,6 @@ defmodule Plausible.Google.ApiTest do
|
||||
end
|
||||
|
||||
test "will fetch and persist import data from Google Analytics", %{site: site, buffer: buffer} do
|
||||
finch_double =
|
||||
Finch
|
||||
|> stub(:request, fn _, _, _ ->
|
||||
{:ok, %Finch.Response{status: 200, body: @ok_response}}
|
||||
end)
|
||||
|
||||
request = %Plausible.Google.ReportRequest{
|
||||
dataset: "imported_exit_pages",
|
||||
view_id: "123",
|
||||
@ -33,8 +30,36 @@ defmodule Plausible.Google.ApiTest do
|
||||
page_size: 10_000
|
||||
}
|
||||
|
||||
expect(
|
||||
Plausible.HTTPClient.Mock,
|
||||
:post,
|
||||
fn
|
||||
"https://analyticsreporting.googleapis.com/v4/reports:batchGet",
|
||||
[{"Authorization", "Bearer fake-token"}],
|
||||
%{
|
||||
reportRequests: [
|
||||
%{
|
||||
dateRanges: [%{endDate: ~D[2022-02-01], startDate: ~D[2022-01-01]}],
|
||||
dimensions: [
|
||||
%{histogramBuckets: [], name: "ga:date"},
|
||||
%{histogramBuckets: [], name: "ga:exitPagePath"}
|
||||
],
|
||||
hideTotals: true,
|
||||
hideValueRanges: true,
|
||||
metrics: [%{expression: "ga:users"}, %{expression: "ga:exits"}],
|
||||
orderBys: [%{fieldName: "ga:date", sortOrder: "DESCENDING"}],
|
||||
pageSize: 10000,
|
||||
pageToken: nil,
|
||||
viewId: "123"
|
||||
}
|
||||
]
|
||||
},
|
||||
[receive_timeout: 60_000] ->
|
||||
{:ok, %Finch.Response{status: 200, body: @ok_response}}
|
||||
end
|
||||
)
|
||||
|
||||
Api.fetch_and_persist(site, request,
|
||||
http_client: finch_double,
|
||||
sleep_time: 0,
|
||||
buffer: buffer
|
||||
)
|
||||
@ -52,13 +77,21 @@ defmodule Plausible.Google.ApiTest do
|
||||
site: site,
|
||||
buffer: buffer
|
||||
} do
|
||||
finch_double =
|
||||
Finch
|
||||
|> stub(:request, fn _, _, _ -> {:error, :timeout} end)
|
||||
|> stub(:request, fn _, _, _ -> {:error, :nx_domain} end)
|
||||
|> stub(:request, fn _, _, _ -> {:error, :closed} end)
|
||||
|> stub(:request, fn _, _, _ -> {:ok, %Finch.Response{status: 503}} end)
|
||||
|> stub(:request, fn _, _, _ -> {:ok, %Finch.Response{status: 502}} end)
|
||||
expect(
|
||||
Plausible.HTTPClient.Mock,
|
||||
:post,
|
||||
5,
|
||||
fn
|
||||
"https://analyticsreporting.googleapis.com/v4/reports:batchGet",
|
||||
_,
|
||||
_,
|
||||
[receive_timeout: 60_000] ->
|
||||
Enum.random([
|
||||
{:error, %Mint.TransportError{reason: :nxdomain}},
|
||||
{:error, %{reason: %Finch.Response{status: 500}}}
|
||||
])
|
||||
end
|
||||
)
|
||||
|
||||
request = %Plausible.Google.ReportRequest{
|
||||
view_id: "123",
|
||||
@ -72,25 +105,23 @@ defmodule Plausible.Google.ApiTest do
|
||||
|
||||
assert {:error, :request_failed} =
|
||||
Api.fetch_and_persist(site, request,
|
||||
http_client: finch_double,
|
||||
sleep_time: 0,
|
||||
buffer: buffer
|
||||
)
|
||||
|
||||
assert_receive({Finch, :request, [_, _, [receive_timeout: 60_000]]})
|
||||
assert_receive({Finch, :request, [_, _, [receive_timeout: 60_000]]})
|
||||
assert_receive({Finch, :request, [_, _, [receive_timeout: 60_000]]})
|
||||
assert_receive({Finch, :request, [_, _, [receive_timeout: 60_000]]})
|
||||
assert_receive({Finch, :request, [_, _, [receive_timeout: 60_000]]})
|
||||
end
|
||||
|
||||
test "does not fail when report does not have rows key", %{site: site, buffer: buffer} do
|
||||
finch_double =
|
||||
Finch
|
||||
|> stub(:request, fn _, _, _ ->
|
||||
{:ok,
|
||||
%Finch.Response{status: 200, body: File.read!("fixture/ga_report_empty_rows.json")}}
|
||||
end)
|
||||
expect(
|
||||
Plausible.HTTPClient.Mock,
|
||||
:post,
|
||||
fn
|
||||
"https://analyticsreporting.googleapis.com/v4/reports:batchGet",
|
||||
_,
|
||||
_,
|
||||
[receive_timeout: 60_000] ->
|
||||
{:ok, %Finch.Response{status: 200, body: @no_report_response}}
|
||||
end
|
||||
)
|
||||
|
||||
request = %Plausible.Google.ReportRequest{
|
||||
dataset: "imported_exit_pages",
|
||||
@ -105,14 +136,92 @@ defmodule Plausible.Google.ApiTest do
|
||||
|
||||
assert :ok ==
|
||||
Api.fetch_and_persist(site, request,
|
||||
http_client: finch_double,
|
||||
sleep_time: 0,
|
||||
buffer: buffer
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch_stats/3" do
|
||||
describe "fetch_stats/3 errors" do
|
||||
setup %{user: user, site: site} do
|
||||
insert(:google_auth,
|
||||
user: user,
|
||||
site: site,
|
||||
property: "sc-domain:dummy.test",
|
||||
expires: NaiveDateTime.add(NaiveDateTime.utc_now(), 3600)
|
||||
)
|
||||
|
||||
:ok
|
||||
end
|
||||
|
||||
test "returns generic google_auth_error on 401/403", %{site: site} do
|
||||
expect(
|
||||
Plausible.HTTPClient.Mock,
|
||||
:post,
|
||||
fn
|
||||
"https://www.googleapis.com/webmasters/v3/sites/sc-domain%3Adummy.test/searchAnalytics/query",
|
||||
[{"Authorization", "Bearer 123"}],
|
||||
%{
|
||||
dimensionFilterGroups: %{},
|
||||
dimensions: ["query"],
|
||||
endDate: "2022-01-05",
|
||||
rowLimit: 5,
|
||||
startDate: "2022-01-01"
|
||||
} ->
|
||||
{:error, %{reason: %Finch.Response{status: Enum.random([401, 403])}}}
|
||||
end
|
||||
)
|
||||
|
||||
query = %Plausible.Stats.Query{date_range: Date.range(~D[2022-01-01], ~D[2022-01-05])}
|
||||
|
||||
assert {:error, "google_auth_error"} = Plausible.Google.Api.fetch_stats(site, query, 5)
|
||||
end
|
||||
|
||||
test "returns whatever error code google returns on API client error", %{site: site} do
|
||||
expect(
|
||||
Plausible.HTTPClient.Mock,
|
||||
:post,
|
||||
fn
|
||||
"https://www.googleapis.com/webmasters/v3/sites/sc-domain%3Adummy.test/searchAnalytics/query",
|
||||
_,
|
||||
_ ->
|
||||
{:error, %{reason: %Finch.Response{status: 400, body: %{"error" => "some_error"}}}}
|
||||
end
|
||||
)
|
||||
|
||||
query = %Plausible.Stats.Query{date_range: Date.range(~D[2022-01-01], ~D[2022-01-05])}
|
||||
|
||||
assert {:error, "some_error"} = Plausible.Google.Api.fetch_stats(site, query, 5)
|
||||
end
|
||||
|
||||
test "returns generic HTTP error and logs it", %{site: site} do
|
||||
expect(
|
||||
Plausible.HTTPClient.Mock,
|
||||
:post,
|
||||
fn
|
||||
"https://www.googleapis.com/webmasters/v3/sites/sc-domain%3Adummy.test/searchAnalytics/query",
|
||||
_,
|
||||
_ ->
|
||||
{:error, Finch.Error.exception(:some_reason)}
|
||||
end
|
||||
)
|
||||
|
||||
query = %Plausible.Stats.Query{date_range: Date.range(~D[2022-01-01], ~D[2022-01-05])}
|
||||
|
||||
log =
|
||||
capture_log(fn ->
|
||||
assert {:error, "failed_to_list_stats"} =
|
||||
Plausible.Google.Api.fetch_stats(site, query, 5)
|
||||
end)
|
||||
|
||||
assert log =~ "Google Analytics: failed to list stats: %Finch.Error{reason: :some_reason}"
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetch_stats/3 with VCR cassetes" do
|
||||
# We need real HTTP Client for VCR tests
|
||||
setup_patch_env(:http_impl, Plausible.HTTPClient)
|
||||
|
||||
test "returns name and visitor count", %{user: user, site: site} do
|
||||
use_cassette "google_analytics_stats", match_requests_on: [:request_body] do
|
||||
insert(:google_auth,
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule Plausible.Google.BufferTest do
|
||||
use Plausible.DataCase, async: false
|
||||
import Plausible.TestUtils
|
||||
|
||||
import Ecto.Query
|
||||
alias Plausible.Google.Buffer
|
||||
|
||||
@ -8,10 +8,7 @@ defmodule Plausible.Google.BufferTest do
|
||||
|
||||
defp set_buffer_size(_setup_args) do
|
||||
google_setting = Application.get_env(:plausible, :google)
|
||||
on_exit(fn -> Application.put_env(:plausible, :google, google_setting) end)
|
||||
test_setting = Keyword.put(google_setting, :max_buffer_size, 10)
|
||||
Application.put_env(:plausible, :google, test_setting)
|
||||
|
||||
patch_env(:google, Keyword.put(google_setting, :max_buffer_size, 10))
|
||||
:ok
|
||||
end
|
||||
|
||||
|
@ -2,9 +2,10 @@ defmodule Plausible.Google.Api.VCRTest do
|
||||
use Plausible.DataCase, async: false
|
||||
use ExVCR.Mock, adapter: ExVCR.Adapter.Finch
|
||||
require Ecto.Query
|
||||
import Plausible.TestUtils
|
||||
|
||||
setup [:create_user, :create_site]
|
||||
# We need real HTTP Client for VCR tests
|
||||
setup_patch_env(:http_impl, Plausible.HTTPClient)
|
||||
|
||||
test "imports page views from Google Analytics", %{site: site} do
|
||||
use_cassette "google_analytics_import#1", match_requests_on: [:request_body] do
|
||||
|
@ -102,6 +102,18 @@ defmodule Plausible.HTTPClientTest do
|
||||
HTTPClient.post(bypass_url(bypass, path: "/any"), headers_no_content_type, params)
|
||||
end
|
||||
|
||||
test "post/4 accepts finch request opts", %{bypass: bypass} do
|
||||
Bypass.expect_once(bypass, "POST", "/timeout", fn conn ->
|
||||
Process.sleep(500)
|
||||
Conn.resp(conn, 200, "ok")
|
||||
end)
|
||||
|
||||
assert {:error, %Mint.TransportError{reason: :timeout}} ==
|
||||
HTTPClient.post(bypass_url(bypass, path: "/timeout"), [], %{}, receive_timeout: 100)
|
||||
|
||||
Bypass.down(bypass)
|
||||
end
|
||||
|
||||
test "non-200 responses are tagged as errors", %{bypass: bypass} do
|
||||
Bypass.expect_once(bypass, "GET", "/get", fn conn ->
|
||||
Conn.resp(conn, 300, "oops")
|
||||
|
@ -1,7 +1,6 @@
|
||||
defmodule Plausible.ImportedTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
use Timex
|
||||
import Plausible.TestUtils
|
||||
|
||||
@user_id 123
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule Plausible.PurgeTest do
|
||||
use Plausible.DataCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
setup do
|
||||
site = insert(:site, stats_start_date: ~D[2020-01-01])
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule Plausible.SiteAdminTest do
|
||||
use Plausible.DataCase, async: true
|
||||
import Plausible.TestUtils
|
||||
|
||||
alias Plausible.{SiteAdmin, ClickhouseRepo, ClickhouseEvent, ClickhouseSession}
|
||||
|
||||
describe "transfer_data" do
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule Plausible.SitesTest do
|
||||
use Plausible.DataCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
alias Plausible.Sites
|
||||
|
||||
describe "is_member?" do
|
||||
|
@ -50,14 +50,7 @@ defmodule PlausibleWeb.CaptchaTest do
|
||||
end
|
||||
|
||||
describe "with patched application env" do
|
||||
setup do
|
||||
original_env = Application.get_env(:plausible, :hcaptcha)
|
||||
Application.put_env(:plausible, :hcaptcha, sitekey: nil)
|
||||
|
||||
on_exit(fn ->
|
||||
Application.put_env(:plausible, :hcaptcha, original_env)
|
||||
end)
|
||||
end
|
||||
setup_patch_env(:hcaptcha, sitekey: nil)
|
||||
|
||||
test "returns true when disabled" do
|
||||
assert Captcha.verify("disabled")
|
||||
|
@ -1,7 +1,6 @@
|
||||
defmodule PlausibleWeb.Api.ExternalSitesControllerTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
use Plausible.Repo
|
||||
import Plausible.TestUtils
|
||||
|
||||
setup %{conn: conn} do
|
||||
user = insert(:user)
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
setup [:create_user, :create_new_site, :create_api_key, :use_api_key]
|
||||
@user_id 123
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.ExternalStatsController.AuthTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
setup [:create_user, :create_api_key]
|
||||
|
||||
@ -69,12 +68,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AuthTest do
|
||||
|
||||
describe "super admin access" do
|
||||
setup %{user: user} do
|
||||
original_env = Application.get_env(:plausible, :super_admin_user_ids)
|
||||
Application.put_env(:plausible, :super_admin_user_ids, [user.id])
|
||||
|
||||
on_exit(fn ->
|
||||
Application.put_env(:plausible, :super_admin_user_ids, original_env)
|
||||
end)
|
||||
patch_env(:super_admin_user_ids, [user.id])
|
||||
end
|
||||
|
||||
test "can access as a super admin", %{conn: conn, api_key: api_key} do
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
@user_id 1231
|
||||
|
||||
setup [:create_user, :create_new_site, :create_api_key, :use_api_key]
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
setup [:create_user, :create_new_site, :create_api_key, :use_api_key]
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
defmodule PlausibleWeb.Api.InternalControllerTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
use Plausible.Repo
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /api/:domain/status" do
|
||||
setup [:create_user, :log_in]
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.AuthorizationTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "API authorization - as anonymous user" do
|
||||
test "Sends 404 Not found for a site that doesn't exist", %{conn: conn} do
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.BrowsersTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /api/stats/:domain/browsers" do
|
||||
setup [:create_user, :log_in, :create_new_site, :add_imported_data]
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.CitiesTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /api/stats/:domain/cities" do
|
||||
defp seed(%{site: site}) do
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
@user_id 123
|
||||
|
||||
describe "GET /api/stats/:domain/conversions" do
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.CountriesTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /api/stats/:domain/countries" do
|
||||
setup [:create_user, :log_in, :create_new_site, :add_imported_data]
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.CurrentVisitorsTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /api/stats/:domain/current-visitors" do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
@user_id 123
|
||||
|
||||
describe "GET /api/stats/main-graph - plot" do
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /api/stats/:domain/operating_systems" do
|
||||
setup [:create_user, :log_in, :create_new_site, :add_imported_data]
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.PagesTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
@user_id 123
|
||||
|
||||
describe "GET /api/stats/:domain/pages" do
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.RegionsTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /api/stats/:domain/regions" do
|
||||
defp seed(%{site: site}) do
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.ScreenSizesTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /api/stats/:domain/browsers" do
|
||||
setup [:create_user, :log_in, :create_new_site, :add_imported_data]
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.SourcesTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
@user_id 123
|
||||
|
||||
describe "GET /api/stats/:domain/sources" do
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /api/stats/:domain/suggestions/:filter_name" do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
@ -1,6 +1,6 @@
|
||||
defmodule PlausibleWeb.Api.StatsController.TopStatsTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
@user_id 123
|
||||
|
||||
describe "GET /api/stats/top-stats - default" do
|
||||
|
@ -2,7 +2,6 @@ defmodule PlausibleWeb.AuthControllerTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
use Bamboo.Test
|
||||
use Plausible.Repo
|
||||
import Plausible.TestUtils
|
||||
|
||||
import Mox
|
||||
setup :verify_on_exit!
|
||||
|
@ -1,6 +1,5 @@
|
||||
defmodule PlausibleWeb.BillingControllerTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /upgrade" do
|
||||
setup [:create_user, :log_in]
|
||||
|
@ -2,7 +2,6 @@ defmodule PlausibleWeb.Site.InvitationControllerTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
use Plausible.Repo
|
||||
use Bamboo.Test
|
||||
import Plausible.TestUtils
|
||||
|
||||
setup [:create_user, :log_in]
|
||||
|
||||
|
@ -2,7 +2,6 @@ defmodule PlausibleWeb.Site.MembershipControllerTest do
|
||||
use PlausibleWeb.ConnCase
|
||||
use Plausible.Repo
|
||||
use Bamboo.Test
|
||||
import Plausible.TestUtils
|
||||
|
||||
setup [:create_user, :log_in]
|
||||
|
||||
|
@ -3,7 +3,10 @@ defmodule PlausibleWeb.SiteControllerTest do
|
||||
use Plausible.Repo
|
||||
use Bamboo.Test
|
||||
use Oban.Testing, repo: Plausible.Repo
|
||||
import Plausible.TestUtils
|
||||
|
||||
import ExUnit.CaptureLog
|
||||
import Mox
|
||||
setup :verify_on_exit!
|
||||
|
||||
describe "GET /sites/new" do
|
||||
setup [:create_user, :log_in]
|
||||
@ -384,6 +387,118 @@ defmodule PlausibleWeb.SiteControllerTest do
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /:webiste/settings/search-console for self-hosting" do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
test "display search console settings", %{conn: conn, site: site} do
|
||||
conn = get(conn, "/#{site.domain}/settings/search-console")
|
||||
resp = html_response(conn, 200)
|
||||
assert resp =~ "An extra step is needed"
|
||||
assert resp =~ "Google Search Console integration"
|
||||
assert resp =~ "self-hosting-configuration"
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /:webiste/settings/search-console" do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
setup_patch_env(:google, client_id: "some", api_url: "https://www.googleapis.com")
|
||||
|
||||
setup %{site: site, user: user} = context do
|
||||
insert(:google_auth, user: user, site: site, property: "sc-domain:#{site.domain}")
|
||||
context
|
||||
end
|
||||
|
||||
test "displays appropriate error in case of google account `google_auth_error`", %{
|
||||
conn: conn,
|
||||
site: site
|
||||
} do
|
||||
expect(
|
||||
Plausible.HTTPClient.Mock,
|
||||
:get,
|
||||
fn
|
||||
"https://www.googleapis.com/webmasters/v3/sites",
|
||||
[{"Content-Type", "application/json"}, {"Authorization", "Bearer 123"}] ->
|
||||
{:error, %{reason: %Finch.Response{status: Enum.random([401, 403])}}}
|
||||
end
|
||||
)
|
||||
|
||||
conn = get(conn, "/#{site.domain}/settings/search-console")
|
||||
resp = html_response(conn, 200)
|
||||
assert resp =~ "Your Search Console account hasn't been connected successfully"
|
||||
assert resp =~ "Please unlink your Google account and try linking it again"
|
||||
end
|
||||
|
||||
test "displays docs link error in case of `invalid_grant`", %{
|
||||
conn: conn,
|
||||
site: site
|
||||
} do
|
||||
expect(
|
||||
Plausible.HTTPClient.Mock,
|
||||
:get,
|
||||
fn
|
||||
"https://www.googleapis.com/webmasters/v3/sites",
|
||||
[{"Content-Type", "application/json"}, {"Authorization", "Bearer 123"}] ->
|
||||
{:error, %{reason: %Finch.Response{status: 400, body: %{"error" => "invalid_grant"}}}}
|
||||
end
|
||||
)
|
||||
|
||||
conn = get(conn, "/#{site.domain}/settings/search-console")
|
||||
resp = html_response(conn, 200)
|
||||
|
||||
assert resp =~
|
||||
"https://plausible.io/docs/google-search-console-integration#i-get-the-invalid-grant-error"
|
||||
end
|
||||
|
||||
test "displays generic error in case of random error code returned by google", %{
|
||||
conn: conn,
|
||||
site: site
|
||||
} do
|
||||
expect(
|
||||
Plausible.HTTPClient.Mock,
|
||||
:get,
|
||||
fn
|
||||
"https://www.googleapis.com/webmasters/v3/sites",
|
||||
[{"Content-Type", "application/json"}, {"Authorization", "Bearer 123"}] ->
|
||||
{:error, %{reason: %Finch.Response{status: 503, body: %{"error" => "some_error"}}}}
|
||||
end
|
||||
)
|
||||
|
||||
conn = get(conn, "/#{site.domain}/settings/search-console")
|
||||
resp = html_response(conn, 200)
|
||||
|
||||
assert resp =~ "Something went wrong, but looks temporary"
|
||||
assert resp =~ "try re-linking your Google account"
|
||||
end
|
||||
|
||||
test "displays generic error and logs a message, in case of random HTTP failure calling google",
|
||||
%{
|
||||
conn: conn,
|
||||
site: site
|
||||
} do
|
||||
expect(
|
||||
Plausible.HTTPClient.Mock,
|
||||
:get,
|
||||
fn
|
||||
"https://www.googleapis.com/webmasters/v3/sites",
|
||||
[{"Content-Type", "application/json"}, {"Authorization", "Bearer 123"}] ->
|
||||
{:error, :nxdomain}
|
||||
end
|
||||
)
|
||||
|
||||
log =
|
||||
capture_log(fn ->
|
||||
conn = get(conn, "/#{site.domain}/settings/search-console")
|
||||
resp = html_response(conn, 200)
|
||||
|
||||
assert resp =~ "Something went wrong, but looks temporary"
|
||||
assert resp =~ "try re-linking your Google account"
|
||||
end)
|
||||
|
||||
assert log =~ "Google Analytics: failed to list sites: :nxdomain"
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /:website/goals/new" do
|
||||
setup [:create_user, :log_in, :create_site]
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
defmodule PlausibleWeb.StatsControllerTest do
|
||||
use PlausibleWeb.ConnCase, async: true
|
||||
use Plausible.Repo
|
||||
import Plausible.TestUtils
|
||||
|
||||
describe "GET /:website - anonymous user" do
|
||||
test "public site - shows site stats", %{conn: conn} do
|
||||
|
@ -2,7 +2,6 @@ defmodule PlausibleWeb.AuthorizeSiteAccessTest do
|
||||
use PlausibleWeb.ConnCase, async: true
|
||||
alias PlausibleWeb.AuthorizeSiteAccess
|
||||
|
||||
import Plausible.TestUtils
|
||||
setup [:create_user, :log_in]
|
||||
|
||||
test "doesn't allow :website bypass with :domain in body", %{conn: conn, user: me} do
|
||||
|
@ -18,6 +18,7 @@ defmodule PlausibleWeb.ConnCase do
|
||||
using do
|
||||
quote do
|
||||
# Import conveniences for testing with connections
|
||||
use Plausible.TestUtils
|
||||
import Plug.Conn
|
||||
import Phoenix.ConnTest
|
||||
alias PlausibleWeb.Router.Helpers, as: Routes
|
||||
|
@ -17,6 +17,7 @@ defmodule Plausible.DataCase do
|
||||
using do
|
||||
quote do
|
||||
use Plausible.Repo
|
||||
use Plausible.TestUtils
|
||||
|
||||
import Ecto.Changeset
|
||||
import Plausible.DataCase
|
||||
|
@ -2,6 +2,34 @@ defmodule Plausible.TestUtils do
|
||||
use Plausible.Repo
|
||||
alias Plausible.Factory
|
||||
|
||||
defmacro __using__(_) do
|
||||
quote do
|
||||
require Plausible.TestUtils
|
||||
import Plausible.TestUtils
|
||||
end
|
||||
end
|
||||
|
||||
defmacro patch_env(env_key, value) do
|
||||
quote do
|
||||
original_env = Application.get_env(:plausible, unquote(env_key))
|
||||
Application.put_env(:plausible, unquote(env_key), unquote(value))
|
||||
|
||||
on_exit(fn ->
|
||||
Application.put_env(:plausible, unquote(env_key), original_env)
|
||||
end)
|
||||
|
||||
{:ok, %{patched_env: true}}
|
||||
end
|
||||
end
|
||||
|
||||
defmacro setup_patch_env(env_key, value) do
|
||||
quote do
|
||||
setup do
|
||||
patch_env(unquote(env_key), unquote(value))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_user(_) do
|
||||
{:ok, user: Factory.insert(:user)}
|
||||
end
|
||||
|
@ -2,7 +2,7 @@ defmodule Plausible.Workers.CheckUsageTest do
|
||||
use Plausible.DataCase, async: true
|
||||
use Bamboo.Test
|
||||
import Double
|
||||
import Plausible.TestUtils
|
||||
|
||||
alias Plausible.Workers.CheckUsage
|
||||
|
||||
setup [:create_user, :create_site]
|
||||
|
@ -2,7 +2,7 @@ defmodule Plausible.Workers.ImportGoogleAnalyticsTest do
|
||||
use Plausible.DataCase
|
||||
use Bamboo.Test
|
||||
import Double
|
||||
import Plausible.TestUtils
|
||||
|
||||
alias Plausible.Workers.ImportGoogleAnalytics
|
||||
|
||||
@imported_data %Plausible.Site.ImportedData{
|
||||
|
@ -1,7 +1,7 @@
|
||||
defmodule Plausible.Workers.NotifyAnnualRenewalTest do
|
||||
use Plausible.DataCase, async: true
|
||||
use Bamboo.Test
|
||||
import Plausible.TestUtils
|
||||
|
||||
alias Plausible.Workers.NotifyAnnualRenewal
|
||||
|
||||
setup [:create_user, :create_site]
|
||||
|
@ -1,5 +1,4 @@
|
||||
defmodule Plausible.Workers.SendEmailReportTest do
|
||||
import Plausible.TestUtils
|
||||
use Plausible.DataCase
|
||||
use Bamboo.Test
|
||||
use Oban.Testing, repo: Plausible.Repo
|
||||
|
@ -2,7 +2,7 @@ defmodule Plausible.Workers.SendSiteSetupEmailsTest do
|
||||
use Plausible.DataCase, async: true
|
||||
use Bamboo.Test
|
||||
use Oban.Testing, repo: Plausible.Repo
|
||||
import Plausible.TestUtils
|
||||
|
||||
alias Plausible.Workers.SendSiteSetupEmails
|
||||
|
||||
describe "when user has not managed to set up the site" do
|
||||
|
@ -2,7 +2,7 @@ defmodule Plausible.Workers.SendTrialNotificationsTest do
|
||||
use Plausible.DataCase
|
||||
use Bamboo.Test
|
||||
use Oban.Testing, repo: Plausible.Repo
|
||||
import Plausible.TestUtils
|
||||
|
||||
alias Plausible.Workers.SendTrialNotifications
|
||||
|
||||
test "does not send a notification if user didn't create a site" do
|
||||
|
Loading…
Reference in New Issue
Block a user