From 5b7b5434c5ca5790e6a6dc99f4b0496c0ad31731 Mon Sep 17 00:00:00 2001 From: Karl-Aksel Puulmann Date: Mon, 9 Dec 2024 11:00:07 +0200 Subject: [PATCH] Remove LegacyDashboardFilterParser (#4882) * Remove LegacyDashboardFilterParser usage in stats_controller * Update tests to avoid legacy dashboard parsing * Update top stats tests Note a few behavioral test changes since dashboard doesn't do wildcards anymore * Update test/plausible_web/controllers/stats_controller_test.exs * Update sources_test Removed test was dead functionality * Update countries_test.exs * Update test/plausible_web/controllers/api/stats_controller/browsers_test.exs * Update test/plausible_web/controllers/api/stats_controller/custom_prop_breakdown_test.exs * Update test/plausible_web/controllers/api/stats_controller/suggestions_test.exs * Remove dead tests * Update pages_test * Update conversions_test.exs * Update funnels_test.exs * Update test/plausible_web/controllers/api/stats_controller/main_graph_test.exs * Update test/plausible_web/controllers/api/stats_controller/suggestions_test.exs * Update test/plausible/stats/query_test.exs * Remove legacy parsing code * Changelog * Inline utils --- CHANGELOG.md | 3 + lib/plausible/stats/filters/filters.ex | 11 +- .../filters/legacy_dashboard_filter_parser.ex | 86 -------- .../stats/filters/stats_api_filter_parser.ex | 20 +- lib/plausible/stats/filters/utils.ex | 25 +-- .../controllers/api/stats_controller.ex | 5 +- .../legacy_dashboard_filter_parser_test.exs | 193 ------------------ test/plausible/stats/query_test.exs | 79 ++++--- .../api/stats_controller/browsers_test.exs | 14 +- .../api/stats_controller/cities_test.exs | 2 +- .../api/stats_controller/conversions_test.exs | 44 ++-- .../api/stats_controller/countries_test.exs | 14 +- .../custom_prop_breakdown_test.exs | 161 +++++++++------ .../api/stats_controller/funnels_test.exs | 7 +- .../api/stats_controller/main_graph_test.exs | 22 +- .../operating_systems_test.exs | 14 +- .../api/stats_controller/pages_test.exs | 77 +++---- .../api/stats_controller/regions_test.exs | 8 +- .../stats_controller/screen_sizes_test.exs | 12 +- .../api/stats_controller/sources_test.exs | 83 ++++---- .../api/stats_controller/suggestions_test.exs | 40 ++-- .../api/stats_controller/top_stats_test.exs | 125 +++++------- .../controllers/stats_controller_test.exs | 11 +- 23 files changed, 396 insertions(+), 660 deletions(-) delete mode 100644 lib/plausible/stats/filters/legacy_dashboard_filter_parser.ex delete mode 100644 test/plausible/stats/legacy_dashboard_filter_parser_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f22b99ca7c6..d6c59f12ec23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ All notable changes to this project will be documented in this file. - Support for `case_sensitive: false` modifiers in Stats API V2 filters for case-insensitive searches. ### Removed + +- Internal stats API routes no longer support legacy dashboard filter format. + ### Changed - Details modal search inputs are now case-insensitive. diff --git a/lib/plausible/stats/filters/filters.ex b/lib/plausible/stats/filters/filters.ex index 0c16ccb3f21e..9f4116f2c8a0 100644 --- a/lib/plausible/stats/filters/filters.ex +++ b/lib/plausible/stats/filters/filters.ex @@ -4,7 +4,7 @@ defmodule Plausible.Stats.Filters do """ alias Plausible.Stats.Filters.QueryParser - alias Plausible.Stats.Filters.{LegacyDashboardFilterParser, StatsAPIFilterParser} + alias Plausible.Stats.Filters.StatsAPIFilterParser @visit_props [ :source, @@ -52,7 +52,6 @@ defmodule Plausible.Stats.Filters do Depending on the format and type of the `filters` argument, returns: - * a decoded list, when `filters` is encoded JSON * a parsed filter list, when `filters` is a filter expression string * the same list, when `filters` is a map @@ -60,9 +59,6 @@ defmodule Plausible.Stats.Filters do ### Examples: - iex> Filters.parse("{\\"page\\":\\"/blog/**\\"}") - [[:matches_wildcard, "event:page", ["/blog/**"]]] - iex> Filters.parse("visit:browser!=Chrome") [[:is_not, "visit:browser", ["Chrome"]]] @@ -71,15 +67,12 @@ defmodule Plausible.Stats.Filters do """ def parse(filters) when is_binary(filters) do case Jason.decode(filters) do - {:ok, filters} when is_map(filters) or is_list(filters) -> parse(filters) + {:ok, filters} when is_list(filters) -> parse(filters) {:ok, _} -> [] {:error, err} -> StatsAPIFilterParser.parse_filter_expression(err.data) end end - def parse(filters) when is_map(filters), - do: LegacyDashboardFilterParser.parse_and_prefix(filters) - def parse(filters) when is_list(filters) do {:ok, parsed_filters} = QueryParser.parse_filters(filters) parsed_filters diff --git a/lib/plausible/stats/filters/legacy_dashboard_filter_parser.ex b/lib/plausible/stats/filters/legacy_dashboard_filter_parser.ex deleted file mode 100644 index a0a6cf0401c6..000000000000 --- a/lib/plausible/stats/filters/legacy_dashboard_filter_parser.ex +++ /dev/null @@ -1,86 +0,0 @@ -defmodule Plausible.Stats.Filters.LegacyDashboardFilterParser do - @moduledoc false - - import Plausible.Stats.Filters.Utils - alias Plausible.Stats.Filters - - @doc """ - This function parses and prefixes the map filter format used by - the internal React dashboard API - """ - def parse_and_prefix(filters_map) do - Enum.flat_map(filters_map, fn {name, val} -> - cond do - name in Filters.visit_props() -> - [filter_value("visit:" <> name, val)] - - name in Filters.event_props() -> - [filter_value("event:" <> name, val)] - - name == "props" -> - parse_props(val) - - true -> - [] - end - end) - end - - def filter_value(key, val) do - {is_negated, val} = parse_negated_prefix(val) - {is_contains, val} = parse_contains_prefix(val) - is_list = list_expression?(val) - is_wildcard = String.contains?(key, ["page", "hostname"]) && wildcard_expression?(val) - val = if is_list, do: parse_member_list(val), else: remove_escape_chars(val) - - cond do - is_negated && is_wildcard && is_list -> - [:matches_wildcard_not, key, val] - - is_negated && is_contains && is_list -> - [:matches_wildcard_not, key, Enum.map(val, &"**#{&1}**")] - - is_wildcard && is_list -> - [:matches_wildcard, key, val] - - is_negated && is_wildcard -> - [:matches_wildcard_not, key, [val]] - - is_negated && is_list -> - [:is_not, key, val] - - is_negated && is_contains -> - [:matches_wildcard_not, key, ["**" <> val <> "**"]] - - is_negated -> - [:is_not, key, [val]] - - is_contains && is_list -> - [:contains, key, val] - - is_list -> - [:is, key, val] - - is_contains -> - [:contains, key, [val]] - - is_wildcard -> - [:matches_wildcard, key, [val]] - - true -> - [:is, key, [val]] - end - end - - defp parse_props(val) do - Enum.map(val, fn {prop_key, prop_val} -> - filter_value("event:props:" <> prop_key, prop_val) - end) - end - - defp parse_negated_prefix("!" <> val), do: {true, val} - defp parse_negated_prefix(val), do: {false, val} - - defp parse_contains_prefix("~" <> val), do: {true, val} - defp parse_contains_prefix(val), do: {false, val} -end diff --git a/lib/plausible/stats/filters/stats_api_filter_parser.ex b/lib/plausible/stats/filters/stats_api_filter_parser.ex index ef3b03cdaa01..341fe9049cdd 100644 --- a/lib/plausible/stats/filters/stats_api_filter_parser.ex +++ b/lib/plausible/stats/filters/stats_api_filter_parser.ex @@ -1,7 +1,7 @@ defmodule Plausible.Stats.Filters.StatsAPIFilterParser do @moduledoc false - import Plausible.Stats.Filters.Utils + @non_escaped_pipe_regex ~r/(? String.split(@non_escaped_pipe_regex) + |> Enum.map(&remove_escape_chars/1) + end + + defp remove_escape_chars(value) do + String.replace(value, "\\|", "|") + end end diff --git a/lib/plausible/stats/filters/utils.ex b/lib/plausible/stats/filters/utils.ex index f072298edcb5..957ef2ab3bc0 100644 --- a/lib/plausible/stats/filters/utils.ex +++ b/lib/plausible/stats/filters/utils.ex @@ -1,28 +1,5 @@ defmodule Plausible.Stats.Filters.Utils do - @moduledoc """ - Contains utility functions shared between `LegacyDashboardFilterParser` - and `StatsAPIFilterParser`. - """ - - @non_escaped_pipe_regex ~r/(? String.split(@non_escaped_pipe_regex) - |> Enum.map(&remove_escape_chars/1) - end - - def remove_escape_chars(value) do - String.replace(value, "\\|", "|") - end + @moduledoc false def split_goals(goals) do Enum.split_with(goals, fn goal -> Plausible.Goal.type(goal) == :event end) diff --git a/lib/plausible_web/controllers/api/stats_controller.ex b/lib/plausible_web/controllers/api/stats_controller.ex index 89b73d5caed6..119a7f7c8415 100644 --- a/lib/plausible_web/controllers/api/stats_controller.ex +++ b/lib/plausible_web/controllers/api/stats_controller.ex @@ -6,7 +6,6 @@ defmodule PlausibleWeb.Api.StatsController do alias Plausible.Stats alias Plausible.Stats.{Query, Comparisons, Filters, Time, TableDecider} - alias Plausible.Stats.Filters.LegacyDashboardFilterParser alias PlausibleWeb.Api.Helpers, as: H require Logger @@ -803,11 +802,9 @@ defmodule PlausibleWeb.Api.StatsController do site = conn.assigns[:site] params = Map.put(params, "property", "visit:referrer") - referrer_filter = LegacyDashboardFilterParser.filter_value("visit:source", referrer) - query = Query.from(site, params, debug_metadata(conn)) - |> Query.add_filter(referrer_filter) + |> Query.add_filter([:is, "visit:source", [referrer]]) pagination = parse_pagination(params) diff --git a/test/plausible/stats/legacy_dashboard_filter_parser_test.exs b/test/plausible/stats/legacy_dashboard_filter_parser_test.exs deleted file mode 100644 index 89002036f848..000000000000 --- a/test/plausible/stats/legacy_dashboard_filter_parser_test.exs +++ /dev/null @@ -1,193 +0,0 @@ -defmodule Plausible.Stats.Legacy.DashboardFilterParserTest do - use ExUnit.Case, async: true - alias Plausible.Stats.Filters.LegacyDashboardFilterParser - - def assert_parsed(filters, expected_output) do - assert LegacyDashboardFilterParser.parse_and_prefix(filters) == expected_output - end - - describe "adding prefix" do - test "adds appropriate prefix to filter" do - %{"page" => "/"} - |> assert_parsed([[:is, "event:page", ["/"]]]) - - %{"goal" => "Signup"} - |> assert_parsed([[:is, "event:goal", ["Signup"]]]) - - %{"goal" => "Visit /blog"} - |> assert_parsed([[:is, "event:goal", ["Visit /blog"]]]) - - %{"source" => "Google"} - |> assert_parsed([[:is, "visit:source", ["Google"]]]) - - %{"referrer" => "cnn.com"} - |> assert_parsed([[:is, "visit:referrer", ["cnn.com"]]]) - - %{"utm_medium" => "search"} - |> assert_parsed([[:is, "visit:utm_medium", ["search"]]]) - - %{"utm_source" => "bing"} - |> assert_parsed([[:is, "visit:utm_source", ["bing"]]]) - - %{"utm_content" => "content"} - |> assert_parsed([[:is, "visit:utm_content", ["content"]]]) - - %{"utm_term" => "term"} - |> assert_parsed([[:is, "visit:utm_term", ["term"]]]) - - %{"screen" => "Desktop"} - |> assert_parsed([[:is, "visit:screen", ["Desktop"]]]) - - %{"browser" => "Opera"} - |> assert_parsed([[:is, "visit:browser", ["Opera"]]]) - - %{"browser_version" => "10.1"} - |> assert_parsed([[:is, "visit:browser_version", ["10.1"]]]) - - %{"os" => "Linux"} - |> assert_parsed([[:is, "visit:os", ["Linux"]]]) - - %{"os_version" => "13.0"} - |> assert_parsed([[:is, "visit:os_version", ["13.0"]]]) - - %{"country" => "EE"} - |> assert_parsed([[:is, "visit:country", ["EE"]]]) - - %{"region" => "EE-12"} - |> assert_parsed([[:is, "visit:region", ["EE-12"]]]) - - %{"city" => "123"} - |> assert_parsed([[:is, "visit:city", ["123"]]]) - - %{"entry_page" => "/blog"} - |> assert_parsed([[:is, "visit:entry_page", ["/blog"]]]) - - %{"exit_page" => "/blog"} - |> assert_parsed([[:is, "visit:exit_page", ["/blog"]]]) - - %{"props" => %{"cta" => "Top"}} - |> assert_parsed([[:is, "event:props:cta", ["Top"]]]) - - %{"hostname" => "dummy.site"} - |> assert_parsed([[:is, "event:hostname", ["dummy.site"]]]) - end - end - - describe "escaping pipe character" do - test "in simple is filter" do - %{"goal" => ~S(Foo \| Bar)} - |> assert_parsed([[:is, "event:goal", ["Foo | Bar"]]]) - end - - test "in member filter" do - %{"page" => ~S(/|\|)} - |> assert_parsed([[:is, "event:page", ["/", "|"]]]) - end - end - - describe "is not filter type" do - test "simple is not filter" do - %{"page" => "!/"} - |> assert_parsed([[:is_not, "event:page", ["/"]]]) - - %{"props" => %{"cta" => "!Top"}} - |> assert_parsed([[:is_not, "event:props:cta", ["Top"]]]) - end - end - - describe "is filter type" do - test "simple is filter" do - %{"page" => "/|/blog"} - |> assert_parsed([[:is, "event:page", ["/", "/blog"]]]) - end - - test "escaping pipe character" do - %{"page" => "/|\\|"} - |> assert_parsed([[:is, "event:page", ["/", "|"]]]) - end - - test "mixed goals" do - %{"goal" => "Signup|Visit /thank-you"} - |> assert_parsed([[:is, "event:goal", ["Signup", "Visit /thank-you"]]]) - - %{"goal" => "Visit /thank-you|Signup"} - |> assert_parsed([[:is, "event:goal", ["Visit /thank-you", "Signup"]]]) - end - end - - describe "matches_wildcard filter type" do - test "parses matches filter type" do - %{"page" => "/|/blog**"} - |> assert_parsed([[:matches_wildcard, "event:page", ["/", "/blog**"]]]) - end - - test "parses not_matches filter type" do - %{"page" => "!/|/blog**"} - |> assert_parsed([[:matches_wildcard_not, "event:page", ["/", "/blog**"]]]) - end - - test "single matches" do - %{"page" => "~blog"} - |> assert_parsed([[:contains, "event:page", ["blog"]]]) - end - - test "negated matches" do - %{"page" => "!~articles"} - |> assert_parsed([[:matches_wildcard_not, "event:page", ["**articles**"]]]) - end - - test "matches member" do - %{"page" => "~articles|blog"} - |> assert_parsed([[:contains, "event:page", ["articles", "blog"]]]) - end - - test "not matches member" do - %{"page" => "!~articles|blog"} - |> assert_parsed([[:matches_wildcard_not, "event:page", ["**articles**", "**blog**"]]]) - end - - test "other filters default to `is` even when wildcard is present" do - %{"country" => "Germa**"} - |> assert_parsed([[:is, "visit:country", ["Germa**"]]]) - end - - test "can be used with `page` filter" do - %{"page" => "!/blog/post-*"} - |> assert_parsed([[:matches_wildcard_not, "event:page", ["/blog/post-*"]]]) - end - - test "other filters default to is_not even when wildcard is present" do - %{"country" => "!Germa**"} - |> assert_parsed([[:is_not, "visit:country", ["Germa**"]]]) - end - end - - describe "is_not filter type" do - test "simple is_not filter" do - %{"page" => "!/|/blog"} - |> assert_parsed([[:is_not, "event:page", ["/", "/blog"]]]) - end - - test "mixed goals" do - %{"goal" => "!Signup|Visit /thank-you"} - |> assert_parsed([ - [:is_not, "event:goal", ["Signup", "Visit /thank-you"]] - ]) - - %{"goal" => "!Visit /thank-you|Signup"} - |> assert_parsed([ - [:is_not, "event:goal", ["Visit /thank-you", "Signup"]] - ]) - end - end - - describe "contains prefix filter type" do - test "can be used with any filter" do - %{"page" => "~/blog/post"} - |> assert_parsed([[:contains, "event:page", ["/blog/post"]]]) - - %{"source" => "~facebook"} - |> assert_parsed([[:contains, "visit:source", ["facebook"]]]) - end - end -end diff --git a/test/plausible/stats/query_test.exs b/test/plausible/stats/query_test.exs index 8716128b7b73..8662bd8f9c48 100644 --- a/test/plausible/stats/query_test.exs +++ b/test/plausible/stats/query_test.exs @@ -194,22 +194,6 @@ defmodule Plausible.Stats.QueryTest do assert q.sample_threshold == 30_000_000 end - describe "filters" do - test "parses goal filter", %{site: site} do - filters = Jason.encode!(%{"goal" => "Signup"}) - q = Query.from(site, %{"period" => "6mo", "filters" => filters}) - - assert q.filters == [[:is, "event:goal", ["Signup"]]] - end - - test "parses source filter", %{site: site} do - filters = Jason.encode!(%{"source" => "Twitter"}) - q = Query.from(site, %{"period" => "6mo", "filters" => filters}) - - assert q.filters == [[:is, "visit:source", ["Twitter"]]] - end - end - describe "&date_range/2" do defp date_range({first, last}, timezone, now \\ nil, opts \\ []) do %Query{ @@ -317,7 +301,7 @@ defmodule Plausible.Stats.QueryTest do "period" => "day", "with_imported" => "true", "property" => "event:props:url", - "filters" => Jason.encode!(%{"props" => %{"author" => "!John Doe"}}) + "filters" => Jason.encode!([[:is_not, "event:props:author", ["John Doe"]]]) }) end @@ -334,7 +318,7 @@ defmodule Plausible.Stats.QueryTest do "period" => "day", "with_imported" => "true", "property" => "event:props:url", - "filters" => Jason.encode!(%{"goal" => goal_name}) + "filters" => Jason.encode!([[:is, "event:goal", [goal_name]]]) }) end) end @@ -363,7 +347,7 @@ defmodule Plausible.Stats.QueryTest do "period" => "day", "with_imported" => "true", "property" => "event:props:url", - "filters" => Jason.encode!(%{"goal" => "404"}) + "filters" => Jason.encode!([[:is, "event:goal", ["404"]]]) }) end @@ -379,7 +363,10 @@ defmodule Plausible.Stats.QueryTest do "with_imported" => "true", "property" => "event:props:url", "filters" => - Jason.encode!(%{"goal" => "Outbound Link: Click", "page" => "/example"}) + Jason.encode!([ + [:is, "event:goal", ["Outbound Link: Click"]], + [:is, "event:page", ["/example"]] + ]) }) end @@ -396,10 +383,10 @@ defmodule Plausible.Stats.QueryTest do "with_imported" => "true", "property" => unquote(property), "filters" => - Jason.encode!(%{ - "goal" => "Outbound Link: Click", - "props" => %{"url" => "https://example.com"} - }) + Jason.encode!([ + [:is, "event:goal", ["Outbound Link: Click"]], + [:is, "event:props:url", ["https://example.com"]] + ]) }) end end @@ -417,10 +404,14 @@ defmodule Plausible.Stats.QueryTest do "with_imported" => "true", "property" => nil, "filters" => - Jason.encode!(%{ - "goal" => "Outbound Link: Click", - "props" => %{"url" => "https://example.com|https://another.example.com"} - }) + Jason.encode!([ + [:is, "event:goal", ["Outbound Link: Click"]], + [ + :is, + "event:props:url", + ["https://example.com", "https://another.example.com"] + ] + ]) }) end @@ -437,10 +428,11 @@ defmodule Plausible.Stats.QueryTest do "with_imported" => "true", "property" => nil, "filters" => - Jason.encode!(%{ - "goal" => "Outbound Link: Click", - "props" => %{"url" => "https://example.com", "path" => "/whatever"} - }) + Jason.encode!([ + [:is, "event:goal", ["Outbound Link: Click"]], + [:is, "event:props:url", ["https://example.com"]], + [:is, "event:props:path", ["/whatever"]] + ]) }) end @@ -456,7 +448,10 @@ defmodule Plausible.Stats.QueryTest do "with_imported" => "true", "property" => nil, "filters" => - Jason.encode!(%{"goal" => "404", "props" => %{"url" => "https://example.com"}}) + Jason.encode!([ + [:is, "event:goal", ["404"]], + [:is, "event:props:url", ["https://example.com"]] + ]) }) end @@ -472,11 +467,11 @@ defmodule Plausible.Stats.QueryTest do "with_imported" => "true", "property" => nil, "filters" => - Jason.encode!(%{ - "goal" => "Outbound Link: Click", - "page" => "/example", - "props" => %{"url" => "https://example.com"} - }) + Jason.encode!([ + [:is, "event:goal", ["Outbound Link: Click"]], + [:is, "event:page", ["/example"]], + [:is, "event:props:url", ["https://example.com"]] + ]) }) end @@ -491,10 +486,10 @@ defmodule Plausible.Stats.QueryTest do "with_imported" => "true", "property" => "visit:source", "filters" => - Jason.encode!(%{ - "goal" => "Outbound Link: Click", - "props" => %{"url" => "https://example.com"} - }) + Jason.encode!([ + [:is, "event:goal", ["Outbound Link: Click"]], + [:is, "event:props:url", ["https://example.com"]] + ]) }) end end diff --git a/test/plausible_web/controllers/api/stats_controller/browsers_test.exs b/test/plausible_web/controllers/api/stats_controller/browsers_test.exs index 60d1fa4a2398..04319216d39c 100644 --- a/test/plausible_web/controllers/api/stats_controller/browsers_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/browsers_test.exs @@ -44,7 +44,7 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "John Doe"}}) + filters = Jason.encode!([[:is, "event:props:author", ["John Doe"]]]) conn = get(conn, "/api/stats/#{site.domain}/browsers?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -79,7 +79,7 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "!John Doe"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["John Doe"]]]) conn = get(conn, "/api/stats/#{site.domain}/browsers?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -97,7 +97,7 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do build(:event, user_id: 1, name: "Signup") ]) - filters = Jason.encode!(%{"goal" => "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get(conn, "/api/stats/#{site.domain}/browsers?period=day&filters=#{filters}") @@ -294,7 +294,7 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) json_response = get( @@ -331,7 +331,7 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do build(:pageview, browser: "Firefox", browser_version: "88.0") ]) - filters = Jason.encode!(%{browser: "Chrome"}) + filters = Jason.encode!([[:is, "visit:browser", ["Chrome"]]]) conn = get( @@ -364,7 +364,7 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do } do populate_stats(site, [build(:pageview, browser: "Chrome", browser_version: "78.0")]) - filters = Jason.encode!(%{browser: "Chrome"}) + filters = Jason.encode!([[:is, "visit:browser", ["Chrome"]]]) conn = get(conn, "/api/stats/#{site.domain}/browser-versions?filters=#{filters}&detailed=true") @@ -386,7 +386,7 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do build(:pageview, browser: "", browser_version: "") ]) - filters = Jason.encode!(%{browser: "(not set)"}) + filters = Jason.encode!([[:is, "visit:browser", ["(not set)"]]]) conn = get( diff --git a/test/plausible_web/controllers/api/stats_controller/cities_test.exs b/test/plausible_web/controllers/api/stats_controller/cities_test.exs index b431739eaa60..ec86dee3a019 100644 --- a/test/plausible_web/controllers/api/stats_controller/cities_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/cities_test.exs @@ -44,7 +44,7 @@ defmodule PlausibleWeb.Api.StatsController.CitiesTest do end test "when list is filtered returns one city only", %{conn: conn, site: site} do - filters = Jason.encode!(%{city: "591632"}) + filters = Jason.encode!([[:is, "visit:city", ["591632"]]]) conn = get(conn, "/api/stats/#{site.domain}/cities?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ diff --git a/test/plausible_web/controllers/api/stats_controller/conversions_test.exs b/test/plausible_web/controllers/api/stats_controller/conversions_test.exs index 0c423b025e6e..95a702619add 100644 --- a/test/plausible_web/controllers/api/stats_controller/conversions_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/conversions_test.exs @@ -76,7 +76,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do insert(:goal, %{site: site, event_name: "Payment"}) - filters = Jason.encode!(%{props: %{"logged_in" => "true"}}) + filters = Jason.encode!([[:is, "event:props:logged_in", ["true"]]]) conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -116,7 +116,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do insert(:goal, %{site: site, event_name: "Payment"}) - filters = Jason.encode!(%{props: %{"logged_in" => "!true"}}) + filters = Jason.encode!([[:is_not, "event:props:logged_in", ["true"]]]) conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -154,7 +154,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do insert(:goal, %{site: site, event_name: "Payment"}) - filters = Jason.encode!(%{props: %{"logged_in" => "(none)"}}) + filters = Jason.encode!([[:is, "event:props:logged_in", ["(none)"]]]) conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -194,7 +194,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do insert(:goal, %{site: site, event_name: "Payment"}) - filters = Jason.encode!(%{props: %{"logged_in" => "!(none)"}}) + filters = Jason.encode!([[:is_not, "event:props:logged_in", ["(none)"]]]) conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -248,7 +248,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do insert(:goal, %{site: site, event_name: "Payment"}) insert(:goal, %{site: site, page_path: "/register"}) - filters = Jason.encode!(%{browser: "Firefox"}) + filters = Jason.encode!([[:is, "visit:browser", ["Firefox"]]]) conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -475,13 +475,13 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do ] # {:is, {:event, event}} filter type - assert get_with_filter.(%{goal: "Signup"}) == expected + assert get_with_filter.([[:is, "event:goal", ["Signup"]]]) == expected # {:member, clauses} filter type - assert get_with_filter.(%{goal: "Signup|Whatever"}) == expected + assert get_with_filter.([[:is, "event:goal", ["Signup", "Whatever"]]]) == expected # {:matches_member, clauses} filter type - assert get_with_filter.(%{goal: "Signup|Visit /whatever*"}) == expected + assert get_with_filter.([[:is, "event:goal", ["Signup", "Visit /whatever*"]]]) == expected end test "does not return custom events with the filtered pageview goal pathname", %{ @@ -497,12 +497,12 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do insert(:goal, %{site: site, page_path: "/register"}) insert(:goal, %{site: site, event_name: "Signup"}) - filters = %{goal: "Visit+/register"} + filters = Jason.encode!([[:is, "event:goal", ["Visit /register"]]]) results = get( conn, - "/api/stats/#{site.domain}/conversions?period=day&filters=#{Jason.encode!(filters)}" + "/api/stats/#{site.domain}/conversions?period=day&filters=#{filters}" ) |> json_response(200) |> Map.get("results") @@ -530,7 +530,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do insert(:goal, %{site: site, page_path: "/register"}) insert(:goal, %{site: site, event_name: "Signup"}) - filters = Jason.encode!(%{goal: "Signup|Visit /register"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup", "Visit /register"]]]) conn = get( @@ -564,7 +564,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do insert(:goal, %{site: site, page_path: "/blog/**"}) insert(:goal, %{site: site, page_path: "/billing/upgrade"}) - filters = Jason.encode!(%{goal: "Visit /blog/**|Visit /billing/upgrade"}) + filters = Jason.encode!([[:is, "event:goal", ["Visit /blog/**", "Visit /billing/upgrade"]]]) conn = get( @@ -602,7 +602,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do insert(:goal, %{site: site, event_name: "CTA"}) insert(:goal, %{site: site, event_name: "Signup"}) - filters = Jason.encode!(%{goal: "Signup|Visit /blog**"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup", "Visit /blog**"]]]) conn = get( @@ -640,7 +640,11 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do insert(:goal, %{site: site, event_name: "Signup"}) - filters = Jason.encode!(%{goal: "Signup", props: %{variant: "(none)"}}) + filters = + Jason.encode!([ + [:is, "event:goal", ["Signup"]], + [:is, "event:props:variant", ["(none)"]] + ]) conn = get( @@ -841,7 +845,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do build(:imported_visitors, visitors: 5, date: ~D[2021-01-01]) ]) - filters = Jason.encode!(%{goal: "Purchase"}) + filters = Jason.encode!([[:is, "event:goal", ["Purchase"]]]) url_query_params = "?filters=#{filters}&period=day&date=2021-01-01&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/conversions#{url_query_params}") @@ -903,7 +907,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do build(:imported_visitors, visitors: 5, date: ~D[2021-01-01]) ]) - filters = Jason.encode!(%{goal: "Purchase|Activation"}) + filters = Jason.encode!([[:is, "event:goal", ["Purchase", "Activation"]]]) url_query_params = "?filters=#{filters}&period=day&date=2021-01-01&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/conversions#{url_query_params}") @@ -961,7 +965,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do build(:imported_visitors, visitors: 5, date: ~D[2021-01-01]) ]) - filters = Jason.encode!(%{goal: "Visit /test"}) + filters = Jason.encode!([[:is, "event:goal", ["Visit /test"]]]) url_query_params = "?filters=#{filters}&period=day&date=2021-01-01&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/conversions#{url_query_params}") @@ -1024,7 +1028,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do build(:imported_visitors, visitors: 5, date: ~D[2021-01-01]) ]) - filters = Jason.encode!(%{goal: "Visit /test|Visit /blog"}) + filters = Jason.encode!([[:is, "event:goal", ["Visit /test", "Visit /blog"]]]) url_query_params = "?filters=#{filters}&period=day&date=2021-01-01&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/conversions#{url_query_params}") @@ -1067,7 +1071,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do build(:imported_visitors, visitors: 10, date: ~D[2021-01-01]) ]) - filters = Jason.encode!(%{page: "/blog/one|/blog/two"}) + filters = Jason.encode!([[:is, "event:page", ["/blog/one", "/blog/two"]]]) q = "?filters=#{filters}&period=day&date=2021-01-01&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/conversions#{q}") @@ -1152,7 +1156,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do build(:imported_visitors, visitors: 4) ]) - filters = Jason.encode!(%{goal: "~Onboarding"}) + filters = Jason.encode!([[:contains, "event:goal", ["Onboarding"]]]) conn = get( diff --git a/test/plausible_web/controllers/api/stats_controller/countries_test.exs b/test/plausible_web/controllers/api/stats_controller/countries_test.exs index db3b2f06972b..585b15bb9146 100644 --- a/test/plausible_web/controllers/api/stats_controller/countries_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/countries_test.exs @@ -88,7 +88,7 @@ defmodule PlausibleWeb.Api.StatsController.CountriesTest do insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{"goal" => "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get(conn, "/api/stats/#{site.domain}/countries?period=day&filters=#{filters}") @@ -134,7 +134,7 @@ defmodule PlausibleWeb.Api.StatsController.CountriesTest do insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{"goal" => "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -189,7 +189,7 @@ defmodule PlausibleWeb.Api.StatsController.CountriesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "John Doe"}}) + filters = Jason.encode!([[:is, "event:props:author", ["John Doe"]]]) conn = get(conn, "/api/stats/#{site.domain}/countries?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -231,7 +231,7 @@ defmodule PlausibleWeb.Api.StatsController.CountriesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "!John Doe"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["John Doe"]]]) conn = get(conn, "/api/stats/#{site.domain}/countries?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -266,7 +266,7 @@ defmodule PlausibleWeb.Api.StatsController.CountriesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "(none)"}}) + filters = Jason.encode!([[:is, "event:props:author", ["(none)"]]]) conn = get(conn, "/api/stats/#{site.domain}/countries?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -306,7 +306,7 @@ defmodule PlausibleWeb.Api.StatsController.CountriesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "!(none)"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["(none)"]]]) conn = get(conn, "/api/stats/#{site.domain}/countries?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -328,7 +328,7 @@ defmodule PlausibleWeb.Api.StatsController.CountriesTest do build(:pageview, country_code: "GB") ]) - filters = Jason.encode!(%{country: "GB"}) + filters = Jason.encode!([[:is, "visit:country", ["GB"]]]) conn = get(conn, "/api/stats/#{site.domain}/countries?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ diff --git a/test/plausible_web/controllers/api/stats_controller/custom_prop_breakdown_test.exs b/test/plausible_web/controllers/api/stats_controller/custom_prop_breakdown_test.exs index dbf16a679232..34c9f1da6654 100644 --- a/test/plausible_web/controllers/api/stats_controller/custom_prop_breakdown_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/custom_prop_breakdown_test.exs @@ -165,7 +165,7 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do ]) insert(:goal, %{site: site, event_name: "Signup"}) - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) prop_key = "variant" conn = @@ -201,7 +201,7 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do ]) insert(:goal, %{site: site, event_name: "Signup"}) - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) prop_key = "variant" conn = @@ -242,10 +242,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do insert(:goal, %{site: site, event_name: "Purchase"}) filters = - Jason.encode!(%{ - goal: "Purchase", - props: %{cost: "0"} - }) + Jason.encode!([ + [:is, "event:goal", ["Purchase"]], + [:is, "event:props:cost", ["0"]] + ]) conn = get( @@ -279,10 +279,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do insert(:goal, %{site: site, event_name: "Purchase"}) filters = - Jason.encode!(%{ - goal: "Purchase", - props: %{cost: "(none)"} - }) + Jason.encode!([ + [:is, "event:goal", ["Purchase"]], + [:is, "event:props:cost", ["(none)"]] + ]) conn = get( @@ -326,10 +326,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do insert(:goal, %{site: site, event_name: "Purchase"}) filters = - Jason.encode!(%{ - goal: "Purchase", - props: %{cost: "!0"} - }) + Jason.encode!([ + [:is, "event:goal", ["Purchase"]], + [:is_not, "event:props:cost", ["0"]] + ]) conn = get( @@ -369,10 +369,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do insert(:goal, %{site: site, event_name: "Purchase"}) filters = - Jason.encode!(%{ - goal: "Purchase", - props: %{cost: "!(none)"} - }) + Jason.encode!([ + [:is, "event:goal", ["Purchase"]], + [:is_not, "event:props:cost", ["(none)"]] + ]) conn = get( @@ -416,10 +416,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do insert(:goal, %{site: site, event_name: "Purchase"}) filters = - Jason.encode!(%{ - goal: "Purchase", - props: %{cost: "0|1"} - }) + Jason.encode!([ + [:is, "event:goal", ["Purchase"]], + [:is, "event:props:cost", ["0", "1"]] + ]) conn = get( @@ -467,10 +467,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do insert(:goal, %{site: site, event_name: "Purchase"}) filters = - Jason.encode!(%{ - goal: "Purchase", - props: %{cost: "1|(none)"} - }) + Jason.encode!([ + [:is, "event:goal", ["Purchase"]], + [:is, "event:props:cost", ["1", "(none)"]] + ]) conn = get( @@ -525,10 +525,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do insert(:goal, %{site: site, event_name: "Purchase"}) filters = - Jason.encode!(%{ - goal: "Purchase", - props: %{cost: "!0|0.01"} - }) + Jason.encode!([ + [:is, "event:goal", ["Purchase"]], + [:is_not, "event:props:cost", ["0", "0.01"]] + ]) conn = get( @@ -576,10 +576,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do insert(:goal, %{site: site, event_name: "Purchase"}) filters = - Jason.encode!(%{ - goal: "Purchase", - props: %{cost: "!0|(none)"} - }) + Jason.encode!([ + [:is, "event:goal", ["Purchase"]], + [:is_not, "event:props:cost", ["0", "(none)"]] + ]) conn = get( @@ -606,7 +606,11 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do ]) insert(:goal, %{site: site, page_path: "/register"}) - filters = Jason.encode!(%{goal: "Visit /register"}) + + filters = + Jason.encode!([ + [:is, "event:goal", ["Visit /register"]] + ]) conn = get( @@ -639,7 +643,13 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do ]) insert(:goal, %{site: site, event_name: "Signup"}) - filters = Jason.encode!(%{goal: "Signup", props: %{"variant" => "B"}}) + + filters = + Jason.encode!([ + [:is, "event:goal", ["Signup"]], + [:is, "event:props:variant", ["B"]] + ]) + prop_key = "variant" conn = @@ -679,11 +689,11 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do insert(:goal, %{site: site, event_name: "ButtonClick"}) filters = - Jason.encode!(%{ - goal: "ButtonClick", - props: %{variant: "A"}, - utm_campaign: "campaignA" - }) + Jason.encode!([ + [:is, "event:goal", ["ButtonClick"]], + [:is, "visit:utm_campaign", ["campaignA"]], + [:is, "event:props:variant", ["A"]] + ]) prop_key = "variant" @@ -725,10 +735,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do insert(:goal, %{site: site, event_name: "ButtonClick"}) filters = - Jason.encode!(%{ - goal: "ButtonClick", - source: "Google" - }) + Jason.encode!([ + [:is, "event:goal", ["ButtonClick"]], + [:is, "visit:source", ["Google"]] + ]) prop_key = "variant" @@ -783,7 +793,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do display_name: "PaymentEUR" }) - filters = Jason.encode!(%{goal: "PaymentEUR"}) + filters = + Jason.encode!([ + [:is, "event:goal", ["PaymentEUR"]] + ]) conn = get( @@ -844,7 +857,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do ) ]) - filters = Jason.encode!(%{goal: "Payment|Payment2"}) + filters = + Jason.encode!([ + [:is, "event:goal", ["Payment", "Payment2"]] + ]) conn = get( @@ -887,7 +903,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do ) ]) - filters = Jason.encode!(%{goal: "Payment|AddToCart"}) + filters = + Jason.encode!([ + [:is, "event:goal", ["Payment", "AddToCart"]] + ]) conn = get( @@ -917,7 +936,7 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do build(:pageview, pathname: "/sipsik", "meta.key": [prop_key], "meta.value": ["Sipsik"]) ]) - filters = Jason.encode!(%{page: "/sipsik"}) + filters = Jason.encode!([[:is, "event:page", ["/sipsik"]]]) conn = get( @@ -947,7 +966,7 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do ) ]) - filters = Jason.encode!(%{browser: "Chrome"}) + filters = Jason.encode!([[:is, "visit:browser", ["Chrome"]]]) conn = get( @@ -974,7 +993,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do build(:pageview, "meta.key": [prop_key], "meta.value": ["Sipsik"]) ]) - filters = Jason.encode!(%{props: %{parim_s6ber: "Sipsik"}}) + filters = + Jason.encode!([ + [:is, "event:props:parim_s6ber", ["Sipsik"]] + ]) conn = get( @@ -1005,7 +1027,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do build(:pageview) ]) - filters = Jason.encode!(%{props: %{parim_s6ber: "!(none)"}}) + filters = + Jason.encode!([ + [:is_not, "event:props:parim_s6ber", ["(none)"]] + ]) conn = get( @@ -1041,7 +1066,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do build(:pageview) ]) - filters = Jason.encode!(%{props: %{key: "~bar"}}) + filters = + Jason.encode!([ + [:contains, "event:props:key", ["bar"]] + ]) conn = get( @@ -1079,7 +1107,11 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do build(:pageview) ]) - filters = Jason.encode!(%{props: %{key: "~bar", other: "1"}}) + filters = + Jason.encode!([ + [:contains, "event:props:key", ["bar"]], + [:is, "event:props:other", ["1"]] + ]) conn = get( @@ -1168,7 +1200,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do build(:imported_visitors, visitors: 9) ]) - filters = Jason.encode!(%{goal: "WP Search Queries"}) + filters = + Jason.encode!([ + [:is, "event:goal", ["WP Search Queries"]] + ]) conn = get( @@ -1216,7 +1251,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do build(:imported_visitors, visitors: 9) ]) - filters = Jason.encode!(%{goal: "404"}) + filters = + Jason.encode!([ + [:is, "event:goal", ["404"]] + ]) conn = get( @@ -1271,7 +1309,10 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do build(:imported_visitors, visitors: 9) ]) - filters = Jason.encode!(%{goal: unquote(goal_name)}) + filters = + Jason.encode!([ + [:is, "event:goal", [unquote(goal_name)]] + ]) conn = get( @@ -1330,7 +1371,11 @@ defmodule PlausibleWeb.Api.StatsController.CustomPropBreakdownTest do build(:imported_visitors, visitors: 9) ]) - filters = Jason.encode!(%{goal: unquote(goal_name), props: %{url: "https://two.com"}}) + filters = + Jason.encode!([ + [:is, "event:goal", [unquote(goal_name)]], + [:is, "event:props:url", ["https://two.com"]] + ]) conn = get( diff --git a/test/plausible_web/controllers/api/stats_controller/funnels_test.exs b/test/plausible_web/controllers/api/stats_controller/funnels_test.exs index d3e55b8a1a07..609511c93b84 100644 --- a/test/plausible_web/controllers/api/stats_controller/funnels_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/funnels_test.exs @@ -121,7 +121,7 @@ defmodule PlausibleWeb.Api.StatsController.FunnelsTest do build(:event, name: "Purchase", user_id: @user_id) ]) - filters = Jason.encode!(%{utm_medium: "social"}) + filters = Jason.encode!([[:is, "visit:utm_medium", ["social"]]]) resp = conn @@ -250,7 +250,7 @@ defmodule PlausibleWeb.Api.StatsController.FunnelsTest do test "event:page", %{conn: conn, site: site} do {:ok, funnel} = setup_funnel(site, @build_funnel_with) - filters = Jason.encode!(%{page: "/pageA"}) + filters = Jason.encode!([[:is, "event:page", ["/pageA"]]]) resp = conn @@ -267,7 +267,8 @@ defmodule PlausibleWeb.Api.StatsController.FunnelsTest do test "event:goal", %{conn: conn, site: site} do {:ok, funnel} = setup_funnel(site, @build_funnel_with) - filters = Jason.encode!(%{goal: "Signup", page: "/pageA"}) + filters = + Jason.encode!([[:is, "event:goal", ["Signup"]], [:is, "event:page", ["/pageA"]]]) resp = conn 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 2d976334e2ce..47704e616735 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 @@ -197,7 +197,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do build(:imported_visitors, date: ~D[2021-01-31]) ]) - filters = Jason.encode!(%{page: "/pageA"}) + filters = Jason.encode!([[:is, "event:page", ["/pageA"]]]) conn = get( @@ -621,7 +621,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do ) ]) - filters = Jason.encode!(%{page: "/"}) + filters = Jason.encode!([[:is, "event:page", ["/"]]]) conn = get( @@ -663,7 +663,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do build(:event, name: "Signup", timestamp: ~N[2021-01-31 00:00:00]) ]) - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -710,7 +710,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do build(:event, name: "Signup", user_id: 123, timestamp: ~N[2021-01-31 00:00:00]) ]) - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -743,7 +743,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do build(:event, name: "Signup", timestamp: ~N[2021-01-11 18:00:00]) ]) - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -773,7 +773,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do build(:event, name: "Signup", timestamp: ~N[2021-08-11 00:00:00]) ]) - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -1325,7 +1325,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do build(:pageview, timestamp: ~N[2021-01-08 00:01:00]) ]) - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -1375,7 +1375,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do ) ]) - filters = Jason.encode!(%{goal: "Payment"}) + filters = Jason.encode!([[:is, "event:goal", ["Payment"]]]) conn = get( @@ -1461,7 +1461,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do ) ]) - filters = Jason.encode!(%{goal: "PaymentUSD"}) + filters = Jason.encode!([[:is, "event:goal", ["PaymentUSD"]]]) conn = get( @@ -1516,7 +1516,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do ) ]) - filters = Jason.encode!(%{goal: "Payment"}) + filters = Jason.encode!([[:is, "event:goal", ["Payment"]]]) conn = get( @@ -1602,7 +1602,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do ) ]) - filters = Jason.encode!(%{goal: "PaymentUSD"}) + filters = Jason.encode!([[:is, "event:goal", ["PaymentUSD"]]]) conn = get( diff --git a/test/plausible_web/controllers/api/stats_controller/operating_systems_test.exs b/test/plausible_web/controllers/api/stats_controller/operating_systems_test.exs index e805ef4e6df0..303575e11223 100644 --- a/test/plausible_web/controllers/api/stats_controller/operating_systems_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/operating_systems_test.exs @@ -36,7 +36,7 @@ defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do %{"name" => "Linux", "visitors" => 1, "percentage" => 50} ] - filters = Jason.encode!(%{os: "(not set)"}) + filters = Jason.encode!([[:is, "visit:os", ["(not set)"]]]) conn2 = get(conn, "/api/stats/#{site.domain}/operating-systems?period=day&filters=#{filters}") @@ -71,7 +71,7 @@ defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do build(:event, user_id: 1, name: "Signup") ]) - filters = Jason.encode!(%{"goal" => "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get(conn, "/api/stats/#{site.domain}/operating-systems?period=day&filters=#{filters}") @@ -111,7 +111,7 @@ defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "John Doe"}}) + filters = Jason.encode!([[:is, "event:props:author", ["John Doe"]]]) conn = get(conn, "/api/stats/#{site.domain}/operating-systems?period=day&filters=#{filters}") @@ -148,7 +148,7 @@ defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "!John Doe"}}) + filters = Jason.encode!([["is_not", "event:props:author", ["John Doe"]]]) conn = get(conn, "/api/stats/#{site.domain}/operating-systems?period=day&filters=#{filters}") @@ -198,7 +198,7 @@ defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do build(:event, user_id: 1, name: "Signup") ]) - filters = Jason.encode!(%{"goal" => "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get(conn, "/api/stats/#{site.domain}/operating-systems?period=day&filters=#{filters}") @@ -237,7 +237,7 @@ defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do ) ]) - filters = Jason.encode!(%{os: "Mac"}) + filters = Jason.encode!([[:is, "visit:os", ["Mac"]]]) conn = get( @@ -272,7 +272,7 @@ defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do build(:pageview, operating_system: "Mac", operating_system_version: "14") ]) - filters = Jason.encode!(%{os: "Mac"}) + filters = Jason.encode!([[:is, "visit:os", ["Mac"]]]) conn = get( diff --git a/test/plausible_web/controllers/api/stats_controller/pages_test.exs b/test/plausible_web/controllers/api/stats_controller/pages_test.exs index c1a5aff851c1..6ae86dce02e4 100644 --- a/test/plausible_web/controllers/api/stats_controller/pages_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/pages_test.exs @@ -37,7 +37,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do build(:pageview, pathname: "/contact", hostname: "e.example.com") ]) - filters = Jason.encode!(%{"hostname" => "*.example.com"}) + filters = Jason.encode!([[:contains, "event:hostname", [".example.com"]]]) conn = get(conn1, "/api/stats/#{site.domain}/pages?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -47,7 +47,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do %{"visitors" => 1, "name" => "/landing"} ] - filters = Jason.encode!(%{"hostname" => "d.example.com"}) + filters = Jason.encode!([[:is, "event:hostname", ["d.example.com"]]]) conn = get(conn1, "/api/stats/#{site.domain}/pages?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -71,7 +71,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do build(:pageview, user_id: 123, pathname: "/") ]) - filters = Jason.encode!(%{props: %{"author" => "John Doe"}}) + filters = Jason.encode!([[:is, "event:props:author", ["John Doe"]]]) conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -97,7 +97,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do build(:pageview, pathname: "/") ]) - filters = Jason.encode!(%{props: %{"author" => "!John Doe"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["John Doe"]]]) conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -134,7 +134,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do build(:pageview, pathname: "/5") ]) - filters = Jason.encode!(%{props: %{"prop" => "~bar"}}) + filters = Jason.encode!([[:contains, "event:props:prop", ["bar"]]]) conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -176,7 +176,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{props: %{"prop" => "~bar|nea"}}) + filters = Jason.encode!([[:contains, "event:props:prop", ["bar", "nea"]]]) conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -214,7 +214,12 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do build(:pageview, pathname: "/5") ]) - filters = Jason.encode!(%{props: %{"prop" => "bar", "number" => "1"}}) + filters = + Jason.encode!([ + [:is, "event:props:prop", ["bar"]], + [:is, "event:props:number", ["1"]] + ]) + conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -258,7 +263,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "John Doe"}}) + filters = Jason.encode!([[:is, "event:props:author", ["John Doe"]]]) conn = get( @@ -322,7 +327,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "!John Doe"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["John Doe"]]]) conn = get( @@ -376,7 +381,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "(none)"}}) + filters = Jason.encode!([[:is, "event:props:author", ["(none)"]]]) conn = get( @@ -434,7 +439,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "!(none)"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["(none)"]]]) conn = get( @@ -497,7 +502,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{props: %{"browser" => "!Chrome|Safari"}}) + filters = Jason.encode!([[:is_not, "event:props:browser", ["Chrome", "Safari"]]]) conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&date=2021-01-01&filters=#{filters}") @@ -537,7 +542,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{props: %{"browser" => "!Chrome|(none)"}}) + filters = Jason.encode!([[:is_not, "event:props:browser", ["Chrome", "(none)"]]]) conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&date=2021-01-01&filters=#{filters}") @@ -578,7 +583,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{page: "/"}) + filters = Jason.encode!([[:is, "event:page", ["/"]]]) conn = get( @@ -667,7 +672,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{page: "/about|/"}) + filters = Jason.encode!([[:is, "event:page", ["/", "/about"]]]) conn = get( @@ -723,7 +728,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{page: "!/irrelevant|/about"}) + filters = Jason.encode!([[:is_not, "event:page", ["/irrelevant", "/about"]]]) conn = get( @@ -770,7 +775,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{page: "/blog/**|/articles/**"}) + filters = Jason.encode!([[:contains, "event:page", ["/blog/", "/articles/"]]]) conn = get( @@ -825,7 +830,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{page: "/blog/(/**|/blog/)/**"}) + filters = Jason.encode!([[:contains, "event:page", ["/blog/(/", "/blog/)/"]]]) conn = get( @@ -880,7 +885,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{page: "!/blog/**|/articles/**"}) + filters = Jason.encode!([[:contains_not, "event:page", ["/blog/", "/articles/"]]]) conn = get( @@ -947,7 +952,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do build(:imported_visitors, visitors: 4) ]) - filters = Jason.encode!(%{goal: "Visit /blog**"}) + filters = Jason.encode!([[:is, "event:goal", ["Visit /blog**"]]]) q = "?period=day&filters=#{filters}&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/pages#{q}") @@ -1032,7 +1037,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{"hostname" => "blog.example.com"}) + filters = Jason.encode!([[:is, "event:hostname", ["blog.example.com"]]]) conn = get( @@ -1112,7 +1117,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{"hostname" => "blog.example.com"}) + filters = Jason.encode!([[:is, "event:hostname", ["blog.example.com"]]]) conn = get( @@ -1290,7 +1295,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{"goal" => "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get(conn, "/api/stats/#{site.domain}/pages?period=day&filters=#{filters}") @@ -1321,7 +1326,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do build(:imported_pages, page: "/ignored", visitors: 10, date: ~D[2021-01-01]) ]) - filters = Jason.encode!(%{"page" => "/"}) + filters = Jason.encode!([[:is, "event:page", ["/"]]]) q = "?period=day&date=2021-01-01&filters=#{filters}&detailed=true&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/pages#{q}") @@ -1370,7 +1375,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do build(:imported_pages, page: "/ignored", visitors: 10, date: ~D[2021-01-01]) ]) - filters = Jason.encode!(%{"page" => "/|/a"}) + filters = Jason.encode!([[:is, "event:page", ["/", "/a"]]]) q = "?period=day&date=2021-01-01&filters=#{filters}&detailed=true&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/pages#{q}") @@ -1426,7 +1431,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do build(:imported_pages, page: "/ignored", visitors: 10, date: ~D[2021-01-01]) ]) - filters = Jason.encode!(%{"page" => "/a**"}) + filters = Jason.encode!([[:contains, "event:page", ["/a"]]]) q = "?period=day&date=2021-01-01&filters=#{filters}&detailed=true&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/pages#{q}") @@ -1607,7 +1612,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "John Doe"}}) + filters = Jason.encode!([[:is, "event:props:author", ["John Doe"]]]) conn = get( @@ -1745,7 +1750,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{"hostname" => "es.example.com"}) + filters = Jason.encode!([[:is, "event:hostname", ["es.example.com"]]]) conn = get( @@ -1778,7 +1783,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do request = fn conn, opts -> page = Keyword.fetch!(opts, :page) limit = Keyword.fetch!(opts, :limit) - filters = Jason.encode!(%{"goal" => "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn |> get( @@ -1838,7 +1843,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{"goal" => "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -1903,7 +1908,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{"entry_page" => "/a**|/b**"}) + filters = Jason.encode!([[:contains, "visit:entry_page", ["/a", "/b"]]]) q = "?period=day&date=2021-01-01&filters=#{filters}&detailed=true&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/entry-pages#{q}") @@ -2031,7 +2036,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{hostname: "es.example.com"}) + filters = Jason.encode!([[:is, "event:hostname", ["es.example.com"]]]) conn = get( @@ -2070,7 +2075,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "John Doe"}}) + filters = Jason.encode!([[:is, "event:props:author", ["John Doe"]]]) conn = get( @@ -2177,7 +2182,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{"goal" => "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -2230,7 +2235,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do ) ]) - filters = Jason.encode!(%{"page" => "/exit1"}) + filters = Jason.encode!([[:is, "event:page", ["/exit1"]]]) conn = get( @@ -2287,7 +2292,7 @@ defmodule PlausibleWeb.Api.StatsController.PagesTest do build(:imported_pages, page: "/bbb", pageviews: 2, date: ~D[2021-01-01]) ]) - filters = Jason.encode!(%{"exit_page" => "!/ignored"}) + filters = Jason.encode!([[:is_not, "visit:exit_page", ["/ignored"]]]) q = "?period=day&date=2021-01-01&filters=#{filters}&detailed=true&with_imported=true" conn = get(conn, "/api/stats/#{site.domain}/exit-pages#{q}") diff --git a/test/plausible_web/controllers/api/stats_controller/regions_test.exs b/test/plausible_web/controllers/api/stats_controller/regions_test.exs index 7addd9a03771..68da14937689 100644 --- a/test/plausible_web/controllers/api/stats_controller/regions_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/regions_test.exs @@ -45,7 +45,7 @@ defmodule PlausibleWeb.Api.StatsController.RegionsTest do end test "when list is filtered returns one city only", %{conn: conn, site: site} do - filters = Jason.encode!(%{region: "EE-39"}) + filters = Jason.encode!([[:is, "visit:region", ["EE-39"]]]) conn = get(conn, "/api/stats/#{site.domain}/regions?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -54,7 +54,7 @@ defmodule PlausibleWeb.Api.StatsController.RegionsTest do end test "malicious input - date", %{conn: conn, site: site} do - filters = Jason.encode!(%{region: "EE-39"}) + filters = Jason.encode!([[:is, "visit:region", ["EE-39"]]]) garbage = "2020-07-30'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'" conn = @@ -68,7 +68,7 @@ defmodule PlausibleWeb.Api.StatsController.RegionsTest do end test "malicious input - from", %{conn: conn, site: site} do - filters = Jason.encode!(%{region: "EE-39"}) + filters = Jason.encode!([[:is, "visit:region", ["EE-39"]]]) garbage = "2020-07-30'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'" conn = @@ -82,7 +82,7 @@ defmodule PlausibleWeb.Api.StatsController.RegionsTest do end test "malicious input - to", %{conn: conn, site: site} do - filters = Jason.encode!(%{region: "EE-39"}) + filters = Jason.encode!([[:is, "visit:region", ["EE-39"]]]) garbage = "2020-07-30'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'" conn = diff --git a/test/plausible_web/controllers/api/stats_controller/screen_sizes_test.exs b/test/plausible_web/controllers/api/stats_controller/screen_sizes_test.exs index de4f1ac07d03..d5795f0dde40 100644 --- a/test/plausible_web/controllers/api/stats_controller/screen_sizes_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/screen_sizes_test.exs @@ -94,7 +94,7 @@ defmodule PlausibleWeb.Api.StatsController.ScreenSizesTest do %{"name" => "Desktop", "visitors" => 1, "percentage" => 50} ] - filters = Jason.encode!(%{screen: "(not set)"}) + filters = Jason.encode!([[:is, "visit:screen", ["(not set)"]]]) conn2 = get(conn, "/api/stats/#{site.domain}/screen-sizes?period=day&filters=#{filters}") assert json_response(conn2, 200)["results"] == [ @@ -144,7 +144,7 @@ defmodule PlausibleWeb.Api.StatsController.ScreenSizesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "John Doe"}}) + filters = Jason.encode!([[:is, "event:props:author", ["John Doe"]]]) conn = get(conn, "/api/stats/#{site.domain}/screen-sizes?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -179,7 +179,7 @@ defmodule PlausibleWeb.Api.StatsController.ScreenSizesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "!John Doe"}}) + filters = Jason.encode!([["is_not", "event:props:author", ["John Doe"]]]) conn = get(conn, "/api/stats/#{site.domain}/screen-sizes?period=day&filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -225,7 +225,7 @@ defmodule PlausibleWeb.Api.StatsController.ScreenSizesTest do build(:imported_visitors, visitors: 2) ]) - filters = Jason.encode!(%{screen: "Desktop"}) + filters = Jason.encode!([[:is, "visit:screen", ["Desktop"]]]) conn = get( @@ -281,7 +281,7 @@ defmodule PlausibleWeb.Api.StatsController.ScreenSizesTest do build(:event, user_id: 1, name: "Signup") ]) - filters = Jason.encode!(%{"goal" => "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get(conn, "/api/stats/#{site.domain}/screen-sizes?period=day&filters=#{filters}") @@ -307,7 +307,7 @@ defmodule PlausibleWeb.Api.StatsController.ScreenSizesTest do ) ]) - filters = Jason.encode!(%{"source" => "!Bad source|Second bad source"}) + filters = Jason.encode!([["is_not", "visit:source", ["Bad source", "Second bad source"]]]) conn = get(conn, "/api/stats/#{site.domain}/screen-sizes?period=day&filters=#{filters}") diff --git a/test/plausible_web/controllers/api/stats_controller/sources_test.exs b/test/plausible_web/controllers/api/stats_controller/sources_test.exs index db5153eaefce..6bff2c857a96 100644 --- a/test/plausible_web/controllers/api/stats_controller/sources_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/sources_test.exs @@ -75,7 +75,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "John Doe"}}) + filters = Jason.encode!([[:is, "event:props:author", ["John Doe"]]]) conn = get( @@ -133,7 +133,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "!John Doe"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["John Doe"]]]) conn = get( @@ -183,7 +183,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "(none)"}}) + filters = Jason.encode!([[:is, "event:props:author", ["(none)"]]]) conn = get( @@ -237,7 +237,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ) ]) - filters = Jason.encode!(%{props: %{"author" => "!(none)"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["(none)"]]]) conn = get( @@ -494,7 +494,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ) ]) - filters = Jason.encode!(%{"page" => "/page1"}) + filters = Jason.encode!([[:is, "event:page", ["/page1"]]]) conn = get(conn, "/api/stats/#{site.domain}/sources?filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -519,7 +519,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ) ]) - filters = Jason.encode!([["is", "event:page", ["/page1"]]]) + filters = Jason.encode!([[:is, "event:page", ["/page1"]]]) conn = get(conn, "/api/stats/#{site.domain}/sources?filters=#{filters}") assert json_response(conn, 200)["results"] == [ @@ -707,7 +707,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ) ]) - filters = Jason.encode!(%{hostname: "one.example.com"}) + filters = Jason.encode!([[:is, "event:hostname", ["one.example.com"]]]) conn = get( @@ -1478,7 +1478,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -1520,7 +1520,11 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ) ]) - filters = Jason.encode!(%{goal: "Signup", hostname: "app.example.com"}) + filters = + Jason.encode!([ + [:is, "event:goal", ["Signup"]], + [:is, "event:hostname", ["app.example.com"]] + ]) conn = get( @@ -1552,7 +1556,12 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{goal: "Signup", hostname: "app.example.com"}) + + filters = + Jason.encode!([ + [:is, "event:goal", ["Signup"]], + [:is, "event:hostname", ["app.example.com"]] + ]) conn = get( @@ -1603,7 +1612,12 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ]) insert(:goal, site: site, event_name: "Download") - filters = Jason.encode!(%{goal: "Download", props: %{"logged_in" => "true"}}) + + filters = + Jason.encode!([ + [:is, "event:goal", ["Download"]], + [:is, "event:props:logged_in", ["true"]] + ]) conn = get( @@ -1655,7 +1669,12 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ]) insert(:goal, site: site, event_name: "Download") - filters = Jason.encode!(%{goal: "Download", props: %{"logged_in" => "!true"}}) + + filters = + Jason.encode!([ + [:is, "event:goal", ["Download"]], + [:is_not, "event:props:logged_in", ["true"]] + ]) conn = get( @@ -1698,7 +1717,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ]) insert(:goal, site: site, page_path: "/register") - filters = Jason.encode!(%{goal: "Visit /register"}) + filters = Jason.encode!([[:is, "event:goal", ["Visit /register"]]]) conn = get( @@ -1784,7 +1803,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ) ]) - filters = Jason.encode!(%{hostname: "one.example.com"}) + filters = Jason.encode!([[:is, "event:hostname", ["one.example.com"]]]) conn = get( @@ -1861,38 +1880,6 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do assert json_response(conn, 200) == %{"results" => terms} end - test "works when filter expression is provided for source", %{ - conn: conn, - site: site - } do - populate_stats(site, [ - build(:pageview, - referrer_source: "DuckDuckGo", - referrer: "duckduckgo.com" - ), - build(:pageview, - referrer_source: "Google", - referrer: "google.com" - ), - build(:pageview, - referrer_source: "Google", - referrer: "google.com" - ) - ]) - - conn1 = get(conn, "/api/stats/#{site.domain}/referrers/!Google?period=day") - - assert json_response(conn1, 200)["results"] == [ - %{"name" => "duckduckgo.com", "visitors" => 1} - ] - - conn2 = get(conn, "/api/stats/#{site.domain}/referrers/Google|DuckDuckGo?period=day") - - assert [entry1, entry2] = json_response(conn2, 200)["results"] - assert %{"name" => "google.com", "visitors" => 2} in [entry1, entry2] - assert %{"name" => "duckduckgo.com", "visitors" => 1} in [entry1, entry2] - end - test "returns top referring urls for a custom goal", %{conn: conn, site: site} do populate_stats(site, [ build(:pageview, @@ -1914,7 +1901,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -1954,7 +1941,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do insert(:goal, site: site, page_path: "/register") - filters = Jason.encode!(%{goal: "Visit /register"}) + filters = Jason.encode!([[:is, "event:goal", ["Visit /register"]]]) conn = get( diff --git a/test/plausible_web/controllers/api/stats_controller/suggestions_test.exs b/test/plausible_web/controllers/api/stats_controller/suggestions_test.exs index ed9ec034940c..a59b336ffd07 100644 --- a/test/plausible_web/controllers/api/stats_controller/suggestions_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/suggestions_test.exs @@ -211,7 +211,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do end test "returns suggestions for browser versions", %{conn: conn, site: site} do - filters = Jason.encode!(%{browser: "Chrome"}) + filters = Jason.encode!([[:is, "visit:browser", ["Chrome"]]]) populate_stats(site, [ build(:pageview, @@ -241,7 +241,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do end test "returns suggestions for OS versions", %{conn: conn, site: site} do - filters = Jason.encode!(%{os: "Mac"}) + filters = Jason.encode!([[:is, "visit:os", ["Mac"]]]) populate_stats(site, [ build(:pageview, @@ -261,7 +261,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do end test "returns suggestions for OS versions with search", %{conn: conn, site: site} do - filters = Jason.encode!(%{os: "Mac"}) + filters = Jason.encode!([[:is, "visit:os", ["Mac"]]]) conn = get( @@ -512,7 +512,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do ) ]) - filters = Jason.encode!(%{props: %{author: "Uku"}}) + filters = Jason.encode!([[:is, "event:props:author", ["Uku"]]]) conn = get( @@ -613,7 +613,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do ) ]) - filters = Jason.encode!(%{props: %{author: "!(none)"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["(none)"]]]) conn = get( @@ -651,7 +651,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do ) ]) - filters = Jason.encode!(%{props: %{author: "!(none)"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["(none)"]]]) conn = get( @@ -687,7 +687,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do ) ]) - filters = Jason.encode!(%{props: %{author: "!(none)"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["(none)"]]]) conn = get( @@ -724,7 +724,11 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do build(:pageview, timestamp: ~N[2022-01-01 00:00:00]) ]) - filters = Jason.encode!(%{props: %{browser_language: "!(none)", author: "Uku Taht"}}) + filters = + Jason.encode!([ + [:is_not, "event:props:browser_language", ["(none)"]], + [:is, "event:props:author", ["Uku Taht"]] + ]) conn = get( @@ -757,7 +761,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do ) ]) - filters = Jason.encode!(%{props: %{author: "!(none)"}}) + filters = Jason.encode!([[:is_not, "event:props:author", ["(none)"]]]) conn = get( @@ -811,7 +815,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do build(:imported_locations, country: "GB") ]) - filters = Jason.encode!(%{source: "Bing"}) + filters = Jason.encode!([[:is, "visit:source", ["Bing"]]]) conn = get( @@ -831,7 +835,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do build(:imported_locations, date: ~D[2019-01-01], country: "EE") ]) - filters = Jason.encode!(%{country: "EE"}) + filters = Jason.encode!([[:is, "visit:country", ["EE"]]]) conn = get( @@ -939,7 +943,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do build(:imported_locations, country: "EE", region: "EE-37") ]) - filters = Jason.encode!(%{source: "Bing"}) + filters = Jason.encode!([[:is, "visit:source", ["Bing"]]]) conn = get( @@ -959,7 +963,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do build(:imported_locations, date: ~D[2019-01-01], region: "EE-39") ]) - filters = Jason.encode!(%{region: "EE-39"}) + filters = Jason.encode!([[:is, "visit:region", ["EE-39"]]]) conn = get( @@ -1041,7 +1045,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do build(:imported_locations, country: "EE", region: "EE-37", city: 588_409) ]) - filters = Jason.encode!(%{source: "Bing"}) + filters = Jason.encode!([[:is, "visit:source", ["Bing"]]]) conn = get( @@ -1061,7 +1065,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do build(:imported_locations, date: ~D[2019-01-01], city: 591_632) ]) - filters = Jason.encode!(%{city: "591632"}) + filters = Jason.encode!([[:is, "visit:city", ["591632"]]]) conn = get( @@ -1121,7 +1125,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do assert json_response(key_conn, 200) == [%{"label" => "url", "value" => "url"}] - filters = Jason.encode!(%{props: %{url: "!(none)"}}) + filters = Jason.encode!([[:is_not, "event:props:url", ["(none)"]]]) value_conn = get( @@ -1366,7 +1370,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do build(:imported_operating_systems, date: ~D[2019-01-01], operating_system: "Windows") ]) - filters = Jason.encode!(%{page: "/blog"}) + filters = Jason.encode!([[:is, "event:page", ["/blog"]]]) conn = get( @@ -1392,7 +1396,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do build(:imported_operating_systems, date: ~D[2019-01-01], operating_system: "Linux") ]) - filters = Jason.encode!(%{os: "!Linux"}) + filters = Jason.encode!([[:is_not, "visit:os", ["Linux"]]]) conn = get( diff --git a/test/plausible_web/controllers/api/stats_controller/top_stats_test.exs b/test/plausible_web/controllers/api/stats_controller/top_stats_test.exs index 438373b8a2a2..0bc99cdc3f26 100644 --- a/test/plausible_web/controllers/api/stats_controller/top_stats_test.exs +++ b/test/plausible_web/controllers/api/stats_controller/top_stats_test.exs @@ -180,7 +180,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{page: "/pageA"}) + filters = Jason.encode!([[:is, "event:page", ["/pageA"]]]) conn = get( @@ -221,7 +221,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{page: "/pageA|/pageB"}) + filters = Jason.encode!([[:is, "event:page", ["/pageA", "/pageB"]]]) conn = get( @@ -262,7 +262,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{page: "!/pageA|/pageC"}) + filters = Jason.encode!([["is_not", "event:page", ["/pageA", "/pageC"]]]) conn = get( @@ -277,7 +277,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ] end - test "calculates time on page when filtered for multiple wildcard pages", %{ + test "calculates time on page when filtered for multiple contains pages", %{ conn: conn, site: site } do @@ -304,7 +304,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{page: "/blog/**|/articles/**"}) + filters = Jason.encode!([[:contains, "event:page", ["/blog/", "/articles/"]]]) conn = get( @@ -319,7 +319,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ] end - test "calculates time on page when filtered for multiple negated wildcard pages", %{ + test "calculates time on page when filtered for multiple negated contains pages", %{ conn: conn, site: site } do @@ -348,7 +348,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{page: "!/blog/**|/articles/**"}) + filters = Jason.encode!([["contains_not", "event:page", ["/blog/", "/articles/"]]]) conn = get( @@ -369,7 +369,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, pathname: "/", user_id: @user_id, timestamp: ~N[2021-01-01 00:10:00]) ]) - filters = Jason.encode!(%{page: "/"}) + filters = Jason.encode!([[:is, "event:page", ["/"]]]) path = "/api/stats/#{site.domain}/top-stats?period=day&date=2021-01-01&filters=#{filters}" assert %{"name" => "Time on page", "value" => 0, "graph_metric" => "time_on_page"} == @@ -389,7 +389,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, pathname: "/", user_id: @user_id, timestamp: ~N[2021-01-01 00:10:00]) ]) - filters = Jason.encode!(%{page: "/"}) + filters = Jason.encode!([[:is, "event:page", ["/"]]]) path = "/api/stats/#{site.domain}/top-stats?period=day&date=2021-01-01&filters=#{filters}" assert %{"name" => "Bounce rate", "value" => 0, "graph_metric" => "bounce_rate"} == @@ -405,7 +405,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, pathname: "/") ]) - filters = Jason.encode!(%{page: "/"}) + filters = Jason.encode!([[:is, "event:page", ["/"]]]) path = "/api/stats/#{site.domain}/top-stats?&filters=#{filters}" assert %{"name" => "Time on page", "value" => 0, "graph_metric" => "time_on_page"} == @@ -424,7 +424,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, user_id: @user_id, timestamp: ~N[2021-01-01 00:03:00], pathname: "/exit") ]) - filters = Jason.encode!(%{page: "/"}) + filters = Jason.encode!([[:is, "event:page", ["/"]]]) path = "/api/stats/#{site.domain}/top-stats?period=day&date=2021-01-01&filters=#{filters}" assert %{ @@ -445,7 +445,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do } do # ┌─p──┬─p2─┬─minus(t2, t)─┬──s─┐ # │ /a │ /b │ 100 │ s1 │ - # │ /a │ /d │ 100 │ s2 │ <- these two get treated + # │ /a │ /d │ 100 │ s2 ��� <- these two get treated # │ /a │ /d │ 0 │ s2 │ <- as single page transition # └────┴────┴──────────────┴────┘ # so that time_on_page(a)=(100+100)/uniq(transition)=200/2=100 @@ -465,7 +465,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, user_id: s2, timestamp: later.(100), pathname: "/d") ]) - filters = Jason.encode!(%{page: "/a"}) + filters = Jason.encode!([[:is, "event:page", ["/a"]]]) path = "/api/stats/#{site.domain}/top-stats?period=day&date=2021-01-01&filters=#{filters}" assert %{"name" => "Time on page", "value" => 100, "graph_metric" => "time_on_page"} == @@ -582,7 +582,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:imported_locations, country: "US", date: ~D[2021-01-01], visitors: 999) ]) - filters = Jason.encode!(%{country: "EE|FR"}) + filters = Jason.encode!([[:is, "visit:country", ["EE", "FR"]]]) q = "?period=day&date=2021-01-01&with_imported=true&filters=#{filters}" conn = get(conn, "/api/stats/#{site.domain}/top-stats#{q}") @@ -628,7 +628,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:imported_pages, page: "/ignored", date: ~D[2021-01-01], visitors: 999) ]) - filters = Jason.encode!(%{page: "/"}) + filters = Jason.encode!([[:is, "event:page", ["/"]]]) q = "?period=day&date=2021-01-01&with_imported=true&filters=#{filters}" conn = get(conn, "/api/stats/#{site.domain}/top-stats#{q}") @@ -734,7 +734,10 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do site: site } do insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{goal: "Signup", page: "/register"}) + + filters = + Jason.encode!([[:is, "event:goal", ["Signup"]], [:is, "event:page", ["/register"]]]) + q = "?period=day&date=2021-03-15&with_imported=true&filters=#{filters}" conn = get(conn, "/api/stats/#{site.domain}/top-stats#{q}") @@ -839,7 +842,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:event, name: "Signup", timestamp: relative_time(minutes: -1)) ]) - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get(conn, "/api/stats/#{site.domain}/top-stats?period=realtime&filters=#{filters}") @@ -863,7 +866,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get(conn, "/api/stats/#{site.domain}/top-stats?period=realtime&filters=#{filters}") @@ -890,7 +893,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do conn: conn, site: site } do - filters = Jason.encode!(%{page: "/A"}) + filters = Jason.encode!([[:is, "event:page", ["/A"]]]) [visitors, visits, pageviews, bounce_rate, time_on_page, scroll_depth] = conn @@ -910,7 +913,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do conn: conn, site: site } do - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) [unique_visitors, unique_conversions, total_conversions, cr] = conn @@ -926,7 +929,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do test "returns graph_metric key for top stats with a goal filter in realtime mode", %{conn: conn, site: site} do - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) [current_visitors, unique_conversions, total_conversions] = conn @@ -946,7 +949,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, country_code: "EE") ]) - filters = Jason.encode!(%{country: "US"}) + filters = Jason.encode!([[:is, "visit:country", ["US"]]]) conn = get( @@ -971,7 +974,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageleave, user_id: 456, timestamp: ~N[2021-01-01 00:00:10], scroll_depth: 80) ]) - filters = Jason.encode!(%{page: "/"}) + filters = Jason.encode!([[:is, "event:page", ["/"]]]) conn = get( @@ -986,36 +989,14 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ] end - test "page glob filter", %{conn: conn, site: site} do - populate_stats(site, [ - build(:pageview, pathname: "/index"), - build(:pageview, pathname: "/blog/post1"), - build(:pageview, pathname: "/blog/post2") - ]) - - filters = Jason.encode!(%{page: "/blog/**"}) - - conn = - get( - conn, - "/api/stats/#{site.domain}/top-stats?period=month&filters=#{filters}" - ) - - res = json_response(conn, 200) - - assert %{"name" => "Unique visitors", "value" => 2, "graph_metric" => "visitors"} in res[ - "top_stats" - ] - end - - test "contains (~) filter", %{conn: conn, site: site} do + test "contains filter", %{conn: conn, site: site} do populate_stats(site, [ build(:pageview, pathname: "/some-blog-post"), build(:pageview, pathname: "/blog/post1"), build(:pageview, pathname: "/another/post") ]) - filters = Jason.encode!(%{page: "~blog"}) + filters = Jason.encode!([[:contains, "event:page", ["blog"]]]) conn = get( @@ -1037,7 +1018,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, screen_size: "Mobile") ]) - filters = Jason.encode!(%{screen: "Desktop"}) + filters = Jason.encode!([[:is, "visit:screen", ["Desktop"]]]) conn = get( @@ -1069,7 +1050,11 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, screen_size: "Mobile", hostname: "blog.example.com") ]) - filters = Jason.encode!(%{screen: "Desktop", hostname: "blog.example.com"}) + filters = + Jason.encode!([ + [:is, "visit:screen", ["Desktop"]], + [:is, "event:hostname", ["blog.example.com"]] + ]) conn = get( @@ -1096,7 +1081,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, browser: "Safari") ]) - filters = Jason.encode!(%{browser: "Chrome"}) + filters = Jason.encode!([[:is, "visit:browser", ["Chrome"]]]) conn = get( @@ -1118,7 +1103,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, operating_system: "Windows") ]) - filters = Jason.encode!(%{os: "Mac"}) + filters = Jason.encode!([[:is, "visit:os", ["Mac"]]]) conn = get( @@ -1153,7 +1138,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, timestamp: ~N[2021-01-01 00:10:00]) ]) - filters = Jason.encode!(%{source: "Google"}) + filters = Jason.encode!([[:is, "visit:source", ["Google"]]]) conn = get( @@ -1176,7 +1161,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, pathname: "/") ]) - filters = Jason.encode!(%{page: "/"}) + filters = Jason.encode!([[:is, "event:page", ["/"]]]) conn = get( @@ -1200,7 +1185,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, pathname: "/blog/post2", hostname: "blog.example.com") ]) - filters = Jason.encode!(%{hostname: "example.com"}) + filters = Jason.encode!([[:is, "event:hostname", ["example.com"]]]) conn = get( @@ -1219,7 +1204,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ] end - test "hostname glob filter", %{conn: conn, site: site} do + test "hostname contains filter", %{conn: conn, site: site} do populate_stats(site, [ build(:pageview, pathname: "/index", hostname: "example.com"), build(:pageview, pathname: "/index", hostname: "example.com", user_id: @user_id), @@ -1229,7 +1214,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:pageview, pathname: "/blog/post2", hostname: "about.example.com") ]) - filters = Jason.encode!(%{hostname: "*example.com"}) + filters = Jason.encode!([[:contains, "event:hostname", ["example.com"]]]) conn = get( @@ -1249,7 +1234,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ] end - test "hostname glob subdomain filter", %{conn: conn, site: site} do + test "hostname contains subdomain filter", %{conn: conn, site: site} do populate_stats(site, [ build(:pageview, pathname: "/index", hostname: "example.com"), build(:pageview, pathname: "/index", hostname: "example.com", user_id: @user_id), @@ -1263,7 +1248,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{hostname: "*.example.com"}) + filters = Jason.encode!([[:contains, "event:hostname", [".example.com"]]]) conn = get( @@ -1294,7 +1279,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:event, name: "Signup") ]) - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -1318,7 +1303,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -1342,7 +1327,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -1369,7 +1354,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( @@ -1423,7 +1408,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{goal: "PaymentUSD"}) + filters = Jason.encode!([[:is, "event:goal", ["PaymentUSD"]]]) conn = get(conn, "/api/stats/#{site.domain}/top-stats?period=all&filters=#{filters}") assert %{"top_stats" => top_stats} = json_response(conn, 200) @@ -1482,7 +1467,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{goal: "Payment|Payment2"}) + filters = Jason.encode!([[:is, "event:goal", ["Payment", "Payment2"]]]) conn = get(conn, "/api/stats/#{site.domain}/top-stats?period=all&filters=#{filters}") assert %{"top_stats" => top_stats} = json_response(conn, 200) @@ -1528,7 +1513,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{goal: "Payment|AddToCart"}) + filters = Jason.encode!([[:is, "event:goal", ["Payment", "AddToCart"]]]) conn = get(conn, "/api/stats/#{site.domain}/top-stats?period=all&filters=#{filters}") assert %{"top_stats" => top_stats} = json_response(conn, 200) @@ -1558,7 +1543,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do build(:event, name: "Signup") ]) - filters = Jason.encode!(%{goal: "Payment|Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Payment", "Signup"]]]) conn = get(conn, "/api/stats/#{site.domain}/top-stats?period=all&filters=#{filters}") assert %{"top_stats" => top_stats} = json_response(conn, 200) @@ -1580,7 +1565,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do %{conn: conn, site: site} do insert(:goal, site: site, event_name: "Payment", currency: "USD") - filters = Jason.encode!(%{goal: "Payment|Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Payment", "Signup"]]]) conn = get(conn, "/api/stats/#{site.domain}/top-stats?period=all&filters=#{filters}") assert %{"top_stats" => top_stats} = json_response(conn, 200) @@ -1615,7 +1600,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{goal: "PaymentWithoutCurrency"}) + filters = Jason.encode!([[:is, "event:goal", ["PaymentWithoutCurrency"]]]) conn = get(conn, "/api/stats/#{site.domain}/top-stats?period=all&filters=#{filters}") assert %{"top_stats" => top_stats} = json_response(conn, 200) @@ -1637,7 +1622,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ) ]) - filters = Jason.encode!(%{goal: "Payment"}) + filters = Jason.encode!([[:is, "event:goal", ["Payment"]]]) conn = get(conn, "/api/stats/#{site.domain}/top-stats?period=all&filters=#{filters}") assert %{"top_stats" => top_stats} = json_response(conn, 200) @@ -1792,7 +1777,7 @@ defmodule PlausibleWeb.Api.StatsController.TopStatsTest do ]) insert(:goal, site: site, event_name: "Signup") - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get( diff --git a/test/plausible_web/controllers/stats_controller_test.exs b/test/plausible_web/controllers/stats_controller_test.exs index 11feceb0fa16..4bb5faa13219 100644 --- a/test/plausible_web/controllers/stats_controller_test.exs +++ b/test/plausible_web/controllers/stats_controller_test.exs @@ -628,7 +628,7 @@ defmodule PlausibleWeb.StatsControllerTest do test "exports filtered data in zipped csvs", %{conn: conn, site: site} do populate_exported_stats(site) - filters = Jason.encode!(%{page: "/some-other-page"}) + filters = Jason.encode!([[:is, "event:page", ["/some-other-page"]]]) conn = get(conn, "/#{site.domain}/export?date=2021-10-20&filters=#{filters}") assert_zip(conn, "30d-filter-path") end @@ -649,7 +649,7 @@ defmodule PlausibleWeb.StatsControllerTest do build(:pageview, "meta.key": ["logged_in"], "meta.value": ["true"]) ]) - filters = Jason.encode!(%{props: %{author: "marko"}}) + filters = Jason.encode!([[:is, "event:props:author", ["marko"]]]) conn = get(conn, "/" <> site.domain <> "/export?period=day&filters=#{filters}") {:ok, zip} = :zip.unzip(response(conn, 200), [:memory]) @@ -768,7 +768,7 @@ defmodule PlausibleWeb.StatsControllerTest do test "exports goal-filtered data in zipped csvs", %{conn: conn, site: site} do populate_exported_stats(site) - filters = Jason.encode!(%{goal: "Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) conn = get(conn, "/#{site.domain}/export?date=2021-10-20&filters=#{filters}") assert_zip(conn, "30d-filter-goal") end @@ -787,7 +787,7 @@ defmodule PlausibleWeb.StatsControllerTest do ]) insert(:goal, site: site, event_name: "Newsletter Signup") - filters = Jason.encode!(%{goal: "Newsletter Signup"}) + filters = Jason.encode!([[:is, "event:goal", ["Newsletter Signup"]]]) conn = get(conn, "/" <> site.domain <> "/export?period=day&filters=#{filters}") {:ok, zip} = :zip.unzip(response(conn, 200), [:memory]) @@ -843,7 +843,8 @@ defmodule PlausibleWeb.StatsControllerTest do insert(:goal, site: site, event_name: "Signup") - conn = get(conn, "/#{site.domain}/export?filters=#{Jason.encode!(%{goal: "Signup"})}") + filters = Jason.encode!([[:is, "event:goal", ["Signup"]]]) + conn = get(conn, "/#{site.domain}/export?filters=#{filters}") assert response = response(conn, 200) {:ok, zip} = :zip.unzip(response, [:memory])