mirror of
https://github.com/plausible/analytics.git
synced 2024-12-26 11:02:52 +03:00
9bae3ccce3
* Add runtime config option for enabled/disabling csv imports and exports
* Use the new option to toggle rendering exports UI
* Disable import buttons when at maximum imports or when option disabled for CSV
* Improve forms for GA import flow
* Add test for maximum imports reached
* Remove "Changed your mind?" prefixing back button
* Hide UA imports in Integrations when `imports_exports` flag is enabled
* Implement `csv_imports_exports` feature flag
* Revert "Add runtime config option for enabled/disabling csv imports and exports"
This reverts commit e30f202dd3
.
* Send import notification email only to the user who ran the import
* Improve rendering of disabled button state
* Put import status heroicon in front of import label
325 lines
10 KiB
Elixir
325 lines
10 KiB
Elixir
defmodule Plausible.Workers.ImportAnalyticsTest do
|
|
use Plausible.DataCase
|
|
use Bamboo.Test
|
|
|
|
alias Plausible.Imported.SiteImport
|
|
alias Plausible.Workers.ImportAnalytics
|
|
|
|
require Plausible.Imported.SiteImport
|
|
|
|
@moduletag capture_log: true
|
|
|
|
describe "perform/1" do
|
|
setup do
|
|
%{
|
|
import_opts: [
|
|
start_date: Timex.today() |> Timex.shift(days: -7),
|
|
end_date: Timex.today()
|
|
]
|
|
}
|
|
end
|
|
|
|
test "updates site import after successful import", %{
|
|
import_opts: import_opts
|
|
} do
|
|
user = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [user])
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, user, import_opts)
|
|
|
|
assert [%{status: SiteImport.pending()}] = Plausible.Imported.list_all_imports(site)
|
|
|
|
# before_start callback triggered
|
|
assert_received {:before_start, import_id}
|
|
|
|
assert :ok =
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
assert [%{id: ^import_id, status: SiteImport.completed()}] =
|
|
Plausible.Imported.list_all_imports(site)
|
|
|
|
# on_success callback triggered
|
|
assert_received {:on_success, ^import_id}
|
|
end
|
|
|
|
test "clears stats_start_date field for the site after successful import", %{
|
|
import_opts: import_opts
|
|
} do
|
|
user = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [user], stats_start_date: ~D[2005-01-01])
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, user, import_opts)
|
|
|
|
assert :ok =
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
site = Repo.reload!(site)
|
|
assert site.stats_start_date == nil
|
|
assert Plausible.Sites.stats_start_date(site) == import_opts[:start_date]
|
|
assert Repo.reload!(site).stats_start_date == import_opts[:start_date]
|
|
end
|
|
|
|
test "sends email to owner after successful import", %{import_opts: import_opts} do
|
|
user = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [user])
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, user, import_opts)
|
|
|
|
assert :ok =
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
assert_email_delivered_with(
|
|
to: [user],
|
|
subject: "Noop data imported for #{site.domain}"
|
|
)
|
|
end
|
|
|
|
test "send email after successful import only to the user who ran the import", %{
|
|
import_opts: import_opts
|
|
} do
|
|
owner = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [owner])
|
|
|
|
importing_user = insert(:user)
|
|
|
|
insert(:site_membership, site: site, user: importing_user, role: :admin)
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, importing_user, import_opts)
|
|
|
|
assert :ok =
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
assert_email_delivered_with(
|
|
to: [importing_user],
|
|
subject: "Noop data imported for #{site.domain}"
|
|
)
|
|
|
|
refute_email_delivered_with(
|
|
to: [owner],
|
|
subject: "Noop data imported for #{site.domain}"
|
|
)
|
|
end
|
|
|
|
test "updates site import record after failed import", %{import_opts: import_opts} do
|
|
user = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [user])
|
|
import_opts = Keyword.put(import_opts, :error, true)
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, user, import_opts)
|
|
|
|
assert {:discard, "Something went wrong"} =
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
assert [%{status: SiteImport.failed()}] = Plausible.Imported.list_all_imports(site)
|
|
end
|
|
|
|
test "clears any orphaned data during import", %{import_opts: import_opts} do
|
|
user = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [user])
|
|
import_opts = Keyword.put(import_opts, :error, true)
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, user, import_opts)
|
|
|
|
populate_stats(site, [
|
|
build(:imported_visitors, import_id: job.args.import_id, pageviews: 10)
|
|
])
|
|
|
|
assert {:discard, _} =
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
assert eventually(fn ->
|
|
count = Plausible.Stats.Clickhouse.imported_pageview_count(site)
|
|
{count == 0, count}
|
|
end)
|
|
|
|
# on_failure callback triggered
|
|
assert_received {:on_failure, _import_id}
|
|
end
|
|
|
|
test "sends email to owner after failed import", %{import_opts: import_opts} do
|
|
user = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [user])
|
|
import_opts = Keyword.put(import_opts, :error, true)
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, user, import_opts)
|
|
|
|
assert {:discard, _} =
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
assert_email_delivered_with(
|
|
to: [user],
|
|
subject: "Noop import failed for #{site.domain}"
|
|
)
|
|
end
|
|
|
|
test "sends email after failed import only to the user who ran the import", %{
|
|
import_opts: import_opts
|
|
} do
|
|
owner = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [owner])
|
|
import_opts = Keyword.put(import_opts, :error, true)
|
|
|
|
importing_user = insert(:user)
|
|
|
|
insert(:site_membership, site: site, user: importing_user, role: :admin)
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, importing_user, import_opts)
|
|
|
|
assert {:discard, _} =
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
assert_email_delivered_with(
|
|
to: [importing_user],
|
|
subject: "Noop import failed for #{site.domain}"
|
|
)
|
|
|
|
refute_email_delivered_with(
|
|
to: [owner],
|
|
subject: "Noop import failed for #{site.domain}"
|
|
)
|
|
end
|
|
end
|
|
|
|
describe "perform/1 notifications" do
|
|
setup do
|
|
on_exit(fn ->
|
|
Ecto.Adapters.SQL.Sandbox.unboxed_run(Plausible.Repo, fn ->
|
|
Repo.delete_all(Plausible.Site)
|
|
Repo.delete_all(Plausible.Auth.User)
|
|
Repo.delete_all(Oban.Job)
|
|
end)
|
|
|
|
:ok
|
|
end)
|
|
|
|
%{
|
|
import_opts: [
|
|
start_date: Timex.today() |> Timex.shift(days: -7),
|
|
end_date: Timex.today()
|
|
]
|
|
}
|
|
end
|
|
|
|
test "sends oban notification to calling process on completion when instructed", %{
|
|
import_opts: import_opts
|
|
} do
|
|
Ecto.Adapters.SQL.Sandbox.unboxed_run(Plausible.Repo, fn ->
|
|
user = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [user])
|
|
site_id = site.id
|
|
import_opts = Keyword.put(import_opts, :listen?, true)
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, user, import_opts)
|
|
import_id = job.args[:import_id]
|
|
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
assert_receive {:notification, :analytics_imports_jobs,
|
|
%{"event" => "complete", "import_id" => ^import_id, "site_id" => ^site_id}}
|
|
end)
|
|
end
|
|
|
|
test "sends oban notification to calling process on permanent failure when instructed", %{
|
|
import_opts: import_opts
|
|
} do
|
|
Ecto.Adapters.SQL.Sandbox.unboxed_run(Plausible.Repo, fn ->
|
|
user = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [user])
|
|
site_id = site.id
|
|
|
|
import_opts =
|
|
import_opts
|
|
|> Keyword.put(:listen?, true)
|
|
|> Keyword.put(:error, true)
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, user, import_opts)
|
|
import_id = job.args[:import_id]
|
|
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
assert_receive {:notification, :analytics_imports_jobs,
|
|
%{"event" => "fail", "import_id" => ^import_id, "site_id" => ^site_id}}
|
|
end)
|
|
end
|
|
|
|
test "sends oban notification to calling process on transient failure when instructed", %{
|
|
import_opts: import_opts
|
|
} do
|
|
Ecto.Adapters.SQL.Sandbox.unboxed_run(Plausible.Repo, fn ->
|
|
user = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [user])
|
|
site_id = site.id
|
|
|
|
import_opts =
|
|
import_opts
|
|
|> Keyword.put(:listen?, true)
|
|
|> Keyword.put(:crash, true)
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, user, import_opts)
|
|
import_id = job.args[:import_id]
|
|
|
|
site_import = Repo.get(Plausible.Imported.SiteImport, import_id)
|
|
|
|
# emulate oban error handler
|
|
try do
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
rescue
|
|
_ -> ImportAnalytics.import_fail_transient(site_import)
|
|
end
|
|
|
|
assert_receive {:notification, :analytics_imports_jobs,
|
|
%{
|
|
"event" => "transient_fail",
|
|
"import_id" => ^import_id,
|
|
"site_id" => ^site_id
|
|
}}
|
|
end)
|
|
end
|
|
|
|
test "sends oban notification to calling process on completion when listener setup separately",
|
|
%{
|
|
import_opts: import_opts
|
|
} do
|
|
Ecto.Adapters.SQL.Sandbox.unboxed_run(Plausible.Repo, fn ->
|
|
user = insert(:user, trial_expiry_date: Timex.today() |> Timex.shift(days: 1))
|
|
site = insert(:site, members: [user])
|
|
site_id = site.id
|
|
|
|
{:ok, job} = Plausible.Imported.NoopImporter.new_import(site, user, import_opts)
|
|
import_id = job.args[:import_id]
|
|
|
|
:ok = Plausible.Imported.Importer.listen()
|
|
|
|
job
|
|
|> Repo.reload!()
|
|
|> ImportAnalytics.perform()
|
|
|
|
assert_receive {:notification, :analytics_imports_jobs,
|
|
%{"event" => "complete", "import_id" => ^import_id, "site_id" => ^site_id}}
|
|
end)
|
|
end
|
|
end
|
|
end
|