analytics/test/workers/import_analytics_test.exs
Adrian Gruntkowski 9bae3ccce3
Improve UI/UX of imports view and GA import flow (#4017)
* 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
2024-04-18 12:12:48 +02:00

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