From 66aceda9e93c9dd7e376eb811994bdc68cb98917 Mon Sep 17 00:00:00 2001 From: Uku Taht Date: Mon, 18 Apr 2022 10:55:36 +0300 Subject: [PATCH] Fix main graph selection with imported data --- lib/plausible/stats/base.ex | 3 +- lib/plausible/stats/imported.ex | 11 ++- .../api/stats_controller/main_graph_test.exs | 68 ++++++++++++++++++- .../controllers/stats_controller_test.exs | 2 +- 4 files changed, 76 insertions(+), 8 deletions(-) diff --git a/lib/plausible/stats/base.ex b/lib/plausible/stats/base.ex index 16b2f55e9..660edadc8 100644 --- a/lib/plausible/stats/base.ex +++ b/lib/plausible/stats/base.ex @@ -289,7 +289,8 @@ defmodule Plausible.Stats.Base do from(s in q, select_merge: %{ :visit_duration => - fragment("toUInt32(ifNotFinite(round(sum(duration * sign) / sum(sign)), 0))") + fragment("toUInt32(ifNotFinite(round(sum(duration * sign) / sum(sign)), 0))"), + visits: fragment("toUInt32(sum(sign))") } ) |> select_session_metrics(rest) diff --git a/lib/plausible/stats/imported.ex b/lib/plausible/stats/imported.ex index f39e8a27b..52cd58634 100644 --- a/lib/plausible/stats/imported.ex +++ b/lib/plausible/stats/imported.ex @@ -18,13 +18,15 @@ defmodule Plausible.Stats.Imported do from(v in "imported_visitors", where: v.site_id == ^site.id, where: v.date >= ^query.date_range.first and v.date <= ^query.date_range.last, - select: %{visitors: sum(v.visitors)} + select: %{} ) + |> select_imported_metrics(metrics) |> apply_interval(query) from(s in Ecto.Query.subquery(native_q), full_join: i in subquery(imported_q), - on: field(s, :date) == field(i, :date) + on: field(s, :date) == field(i, :date), + select: %{date: field(s, :date)} ) |> select_joined_metrics(metrics) end @@ -350,7 +352,10 @@ defmodule Plausible.Stats.Imported do defp select_imported_metrics(q, [:visit_duration | rest]) do q - |> select_merge([i], %{visit_duration: sum(i.visit_duration)}) + |> select_merge([i], %{ + visit_duration: sum(i.visit_duration), + visits: sum(i.visits) + }) |> select_imported_metrics(rest) end diff --git a/test/plausible_web/controllers/api/stats_controller/main_graph_test.exs b/test/plausible_web/controllers/api/stats_controller/main_graph_test.exs index 969ce0698..02fecaa33 100644 --- a/test/plausible_web/controllers/api/stats_controller/main_graph_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/main_graph_test.exs @@ -244,7 +244,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do end describe "GET /api/stats/main-graph - pageviews plot" do - setup [:create_user, :log_in, :create_new_site] + setup [:create_user, :log_in, :create_new_site, :add_imported_data] test "displays pageviews for a month", %{conn: conn, site: site} do populate_stats(site, [ @@ -265,10 +265,32 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do assert List.first(plot) == 2 assert List.last(plot) == 1 end + + test "displays pageviews for a month with imported data", %{conn: conn, site: site} do + populate_stats(site, [ + build(:pageview, timestamp: ~N[2021-01-01 00:00:00]), + build(:pageview, timestamp: ~N[2021-01-31 00:00:00]), + build(:imported_visitors, date: ~D[2021-01-01]), + build(:imported_visitors, date: ~D[2021-01-31]) + ]) + + conn = + get( + conn, + "/api/stats/#{site.domain}/main-graph?period=month&date=2021-01-01&metric=pageviews&with_imported=true" + ) + + assert %{"plot" => plot} = json_response(conn, 200) + + assert Enum.count(plot) == 31 + assert List.first(plot) == 2 + assert List.last(plot) == 2 + assert Enum.sum(plot) == 4 + end end describe "GET /api/stats/main-graph - bounce_rate plot" do - setup [:create_user, :log_in, :create_new_site] + setup [:create_user, :log_in, :create_new_site, :add_imported_data] test "displays bounce_rate for a month", %{conn: conn, site: site} do populate_stats(site, [ @@ -289,10 +311,31 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do assert List.first(plot) == 0 assert List.last(plot) == 100 end + + test "displays bounce rate for a month with imported data", %{conn: conn, site: site} do + populate_stats(site, [ + build(:pageview, timestamp: ~N[2021-01-01 00:00:00]), + build(:pageview, timestamp: ~N[2021-01-31 00:00:00]), + build(:imported_visitors, visits: 1, bounces: 0, date: ~D[2021-01-01]), + build(:imported_visitors, visits: 1, bounces: 1, date: ~D[2021-01-31]) + ]) + + conn = + get( + conn, + "/api/stats/#{site.domain}/main-graph?period=month&date=2021-01-01&metric=bounce_rate&with_imported=true" + ) + + assert %{"plot" => plot} = json_response(conn, 200) + + assert Enum.count(plot) == 31 + assert List.first(plot) == 50 + assert List.last(plot) == 100 + end end describe "GET /api/stats/main-graph - visit_duration plot" do - setup [:create_user, :log_in, :create_new_site] + setup [:create_user, :log_in, :create_new_site, :add_imported_data] test "displays visit_duration for a month", %{conn: conn, site: site} do populate_stats(site, [ @@ -320,5 +363,24 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do assert List.first(plot) == 0 assert List.last(plot) == 300 end + + test "displays visit_duration for a month with imported data", %{conn: conn, site: site} do + populate_stats(site, [ + build(:pageview, user_id: @user_id, timestamp: ~N[2021-01-01 00:10:00]), + build(:pageview, user_id: @user_id, timestamp: ~N[2021-01-01 00:15:00]), + build(:imported_visitors, visits: 1, visit_duration: 100, date: ~D[2021-01-01]) + ]) + + conn = + get( + conn, + "/api/stats/#{site.domain}/main-graph?period=month&date=2021-01-01&metric=visit_duration&with_imported=true" + ) + + assert %{"plot" => plot} = json_response(conn, 200) + + assert Enum.count(plot) == 31 + assert List.first(plot) == 200 + end end end diff --git a/test/plausible_web/controllers/stats_controller_test.exs b/test/plausible_web/controllers/stats_controller_test.exs index dfd5d391e..d1687b290 100644 --- a/test/plausible_web/controllers/stats_controller_test.exs +++ b/test/plausible_web/controllers/stats_controller_test.exs @@ -40,7 +40,7 @@ defmodule PlausibleWeb.StatsControllerTest do test "can not view stats of someone else's website", %{conn: conn} do site = insert(:site) - conn = get(conn, site.domain) + conn = get(conn, "/" <> site.domain) assert html_response(conn, 404) =~ "There's nothing here" end end