analytics/test/workers/import_analytics_test.exs
Adrian Gruntkowski 39aa81a16f
Implement UI for multiple imports (#3727)
* Create a stub of site settings section for imports and exports

* Use legacy site import indication to determine UA import handling

* Add provisional logos for upcoming import sources

* Stub basics of import page

* Add very rudimentary support for multiple UA imports

* Implement imports list as live view

* Add support for opening LV modal from backend and closing from frontend

* Introduce notion of themes to `button` and `button_link` components

* Add confirmation modal on deleting import

* Swap GA4 logo

* Implement disabled state support for `button_link` component

* Disable export and non-implemented import sources

* Use native starts start date for upper boundary of import time range

* Ensure integrations view uses legacy UA import flow

* Remove unnecessary preload in SiteController

* Remove unnecessary exception for legacy imports

* Move API controller stats tests under PlausibleWeb

* Test listing imports

* Add test for explicit listener setup

* Add tests for legacy flag state in UA importer

* Add test for purging legacy import data

* Add tests for `Sites.native_stats_start_date`

* Test forgetting imports

* Add `Stats.Clickhouse.imported_pageview_counts/1` and fix test flakiness

* Show page view counts on imports list

* Add tests for static imports and exports view

* Adjust button look slightly

* Use `case` instead of `cond`

* Make feature flag customisable per site

* Fix buttons and empty state styling

* Add another import to seeds

* Use JS confirm dialog instead of modal for deletion confirmations

* Revert "Add support for opening LV modal from backend and closing from frontend"

This reverts commit 260e6c753032b451542e24be9edc2118790b5a00.

* Default `legacy` to false when inserting new import jobs

* Drop `method` attribute from `button_link` and `unstyled_link` components
2024-02-28 09:34:04 +01:00

255 lines
8.1 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 "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
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)
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])
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, %{"complete" => ^import_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])
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, %{"fail" => ^import_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])
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, %{"transient_fail" => ^import_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])
{: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, %{"complete" => ^import_id}}
end)
end
end
end