Stop counting today in `7d` and `30d` periods + add `28d` and `90d` (#5240)

* change 7d and 30d periods in API v2

* change 7d and 30d periods in legacy API

* add 28d and 90d into the dashboard

* add tests

* add 28d and 90d to public API v2

* changelog

* npm run generate-types

* typo

* fix NPM test

* fix interval_test

* add P shortcut for last month

* hide last 30d from datepicker but keep keybind functional

* fix keybind hints

* Timex to Date + helpful comment

* prettier format

* adjust comment

* mention 30d -> 28d in changelog as well

* make period hidden param new default
This commit is contained in:
RobertJoonas 2025-03-27 10:49:56 +01:00 committed by GitHub
parent 02370c5335
commit 1b4aefb7d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 544 additions and 163 deletions

View File

@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
## Unreleased
### Added
- Two new shorthand time periods `28d` and `90d` available on both dashboard and in public API
- Average scroll depth metric
- Scroll Depth goals
- Dashboard shows comparisons for all reports
@ -25,6 +26,8 @@ All notable changes to this project will be documented in this file.
### Changed
- The "Last 30 days" period is now "Last 28 days" on the dashboard and also the new default. Keyboard shortcut `T` still works for last 30 days.
- Last `7d` and `30d` periods do not include today anymore
- Filters appear in the search bar as ?f=is,page,/docs,/blog&f=... instead of ?filters=((is,page,(/docs,/blog)),...) for Plausible links sent on various platforms to work reliably.
- Details modal search inputs are now case-insensitive.
- Improved report performance in cases where site has a lot of unique pathnames

View File

@ -10,7 +10,7 @@ import { QueryPeriodsPicker } from './query-periods-picker'
const domain = 'picking-query-dates.test'
const periodStorageKey = `period__${domain}`
test('if no period is stored, loads with default value of "Last 30 days", all expected options are present', async () => {
test('if no period is stored, loads with default value of "Last 28 days", all expected options are present', async () => {
expect(localStorage.getItem(periodStorageKey)).toBe(null)
render(<QueryPeriodsPicker />, {
wrapper: (props) => (
@ -18,7 +18,7 @@ test('if no period is stored, loads with default value of "Last 30 days", all ex
)
})
await userEvent.click(screen.getByText('Last 30 days'))
await userEvent.click(screen.getByText('Last 28 days'))
expect(screen.getByTestId('datemenu')).toBeVisible()
expect(screen.getAllByRole('link').map((el) => el.textContent)).toEqual(
@ -27,9 +27,10 @@ test('if no period is stored, loads with default value of "Last 30 days", all ex
['Yesterday', 'E'],
['Realtime', 'R'],
['Last 7 Days', 'W'],
['Last 30 Days', 'T'],
['Last 28 Days', 'F'],
['Last 90 Days', 'N'],
['Month to Date', 'M'],
['Last Month', ''],
['Last Month', 'P'],
['Year to Date', 'Y'],
['Last 12 Months', 'L'],
['All time', 'A'],
@ -46,7 +47,7 @@ test('user can select a new period and its value is stored', async () => {
)
})
await userEvent.click(screen.getByText('Last 30 days'))
await userEvent.click(screen.getByText('Last 28 days'))
expect(screen.getByTestId('datemenu')).toBeVisible()
await userEvent.click(screen.getByText('All time'))
expect(screen.queryByTestId('datemenu')).toBeNull()
@ -162,7 +163,7 @@ test('going back resets the stored query period to previous value', async () =>
}
)
await userEvent.click(screen.getByText('Last 30 days'))
await userEvent.click(screen.getByText('Last 28 days'))
await userEvent.click(screen.getByText('Year to Date'))
expect(localStorage.getItem(periodStorageKey)).toBe('year')

View File

@ -15,7 +15,6 @@ import {
} from '../../navigation/use-app-navigate'
import {
getCompareLinkItem,
last6MonthsLinkItem,
getDatePeriodGroups,
LinkItem,
QueryPeriod,
@ -54,7 +53,7 @@ function QueryPeriodMenuKeybinds({
}
return (
<>
{groups.concat([[last6MonthsLinkItem]]).flatMap((group) =>
{groups.flatMap((group) =>
group
.filter(([[_name, keyboardKey]]) => !!keyboardKey)
.map(([[_name, keyboardKey], { search, onEvent }]) => (
@ -163,7 +162,12 @@ const QueryPeriodMenuInner = ({
{groups.map((group, index) => (
<React.Fragment key={index}>
{group.map(
([[label, keyboardKey], { search, isActive, onEvent }]) => (
([
[label, keyboardKey],
{ search, isActive, onEvent, hidden }
]) => {
if (!hidden) {
return (
<AppNavigationLink
key={label}
data-selected={isActive({ site, query })}
@ -172,9 +176,13 @@ const QueryPeriodMenuInner = ({
onClick={onEvent && ((e) => onEvent(e))}
>
{label}
{!!keyboardKey && <KeybindHint>{keyboardKey}</KeybindHint>}
{!!keyboardKey && (
<KeybindHint>{keyboardKey}</KeybindHint>
)}
</AppNavigationLink>
)
}
}
)}
{index < groups.length - 1 && <MenuSeparator />}
</React.Fragment>

View File

@ -29,7 +29,9 @@ export enum QueryPeriod {
'day' = 'day',
'month' = 'month',
'7d' = '7d',
'28d' = '28d',
'30d' = '30d',
'90d' = '90d',
'6mo' = '6mo',
'12mo' = '12mo',
'year' = 'year',
@ -248,6 +250,7 @@ export type LinkItem = [
query: DashboardQuery
}) => boolean
onEvent?: (event: Pick<Event, 'preventDefault' | 'stopPropagation'>) => void
hidden?: boolean
}
]
@ -329,9 +332,23 @@ export const getDatePeriodGroups = ({
onEvent
}
],
[
['Last 28 Days', 'F'],
{
search: (s) => ({
...s,
...clearedDateSearch,
period: QueryPeriod['28d'],
keybindHint: 'F'
}),
isActive: ({ query }) => query.period === QueryPeriod['28d'],
onEvent
}
],
[
['Last 30 Days', 'T'],
{
hidden: true,
search: (s) => ({
...s,
...clearedDateSearch,
@ -341,6 +358,19 @@ export const getDatePeriodGroups = ({
isActive: ({ query }) => query.period === QueryPeriod['30d'],
onEvent
}
],
[
['Last 90 Days', 'N'],
{
search: (s) => ({
...s,
...clearedDateSearch,
period: QueryPeriod['90d'],
keybindHint: 'N'
}),
isActive: ({ query }) => query.period === QueryPeriod['90d'],
onEvent
}
]
],
[
@ -360,14 +390,14 @@ export const getDatePeriodGroups = ({
}
],
[
['Last Month'],
['Last Month', 'P'],
{
search: (s) => ({
...s,
...clearedDateSearch,
period: QueryPeriod.month,
date: formatISO(lastMonth(site)),
keybindHint: null
keybindHint: 'P'
}),
isActive: ({ query }) =>
query.period === QueryPeriod.month &&
@ -391,6 +421,19 @@ export const getDatePeriodGroups = ({
onEvent
}
],
[
['Last 6 months', 'S'],
{
hidden: true,
search: (s) => ({
...s,
...clearedDateSearch,
period: QueryPeriod['6mo'],
keybindHint: 'S'
}),
isActive: ({ query }) => query.period === QueryPeriod['6mo']
}
],
[
['Last 12 Months', 'L'],
{
@ -428,19 +471,6 @@ export const getDatePeriodGroups = ({
.concat(extraGroups)
}
export const last6MonthsLinkItem: LinkItem = [
['Last 6 months', 'S'],
{
search: (s) => ({
...s,
...clearedDateSearch,
period: QueryPeriod['6mo'],
keybindHint: 'S'
}),
isActive: ({ query }) => query.period === QueryPeriod['6mo']
}
]
export const getCompareLinkItem = ({
query,
site
@ -570,9 +600,15 @@ export function getCurrentPeriodDisplayName({
if (query.period === '7d') {
return 'Last 7 days'
}
if (query.period === '28d') {
return 'Last 28 days'
}
if (query.period === '30d') {
return 'Last 30 days'
}
if (query.period === '90d') {
return 'Last 90 days'
}
if (query.period === 'month') {
if (isThisMonth(site, query.date)) {
return 'Month to Date'

View File

@ -54,7 +54,7 @@ export type DashboardQuery = {
}
export const queryDefaultValue: DashboardQuery = {
period: '30d' as QueryPeriod,
period: '28d' as QueryPeriod,
comparison: null,
match_day_of_week: true,
date: null,

View File

@ -30,7 +30,7 @@ describe('parseSiteFromDataset', () => {
data-current-user-role="owner"
data-current-user-id="1"
data-flags="{}"
data-valid-intervals-by-period='{"12mo":["day","week","month"],"30d":["day","week"],"6mo":["day","week","month"],"7d":["hour","day"],"all":["week","month"],"custom":["day","week","month"],"day":["minute","hour"],"month":["day","week"],"realtime":["minute"],"year":["day","week","month"]}'
data-valid-intervals-by-period='{"12mo":["day","week","month"],"7d":["hour","day"],"28d":["day","week"],"30d":["day","week"],"90d":["day","week","month"],"6mo":["day","week","month"],"all":["week","month"],"custom":["day","week","month"],"day":["minute","hour"],"month":["day","week"],"realtime":["minute"],"year":["day","week","month"]}'
{...attrs}
/>
)
@ -55,9 +55,11 @@ describe('parseSiteFromDataset', () => {
flags: {},
validIntervalsByPeriod: {
'12mo': ['day', 'week', 'month'],
'30d': ['day', 'week'],
'6mo': ['day', 'week', 'month'],
'7d': ['hour', 'day'],
'28d': ['day', 'week'],
'30d': ['day', 'week'],
'90d': ['day', 'week', 'month'],
'6mo': ['day', 'week', 'month'],
all: ['week', 'month'],
custom: ['day', 'week', 'month'],
day: ['minute', 'hour'],

View File

@ -20,7 +20,19 @@ export type Metric =
| "total_revenue"
| "average_revenue"
| "scroll_depth";
export type DateRangeShorthand = "30m" | "realtime" | "all" | "day" | "7d" | "30d" | "month" | "6mo" | "12mo" | "year";
export type DateRangeShorthand =
| "30m"
| "realtime"
| "all"
| "day"
| "7d"
| "28d"
| "30d"
| "90d"
| "month"
| "6mo"
| "12mo"
| "year";
/**
* @minItems 2
* @maxItems 2

View File

@ -225,14 +225,12 @@ defmodule Plausible.Stats.Filters.QueryParser do
{:ok, DateTimeRange.new!(date, date, site.timezone)}
end
defp parse_time_range(site, "7d", date, _now) do
first = date |> Date.add(-6)
{:ok, DateTimeRange.new!(first, date, site.timezone)}
end
defp parse_time_range(site, "30d", date, _now) do
first = date |> Date.add(-30)
{:ok, DateTimeRange.new!(first, date, site.timezone)}
defp parse_time_range(site, shorthand, date, _now)
when shorthand in ["7d", "28d", "30d", "90d"] do
{days, "d"} = Integer.parse(shorthand)
last = date |> Date.add(-1)
first = date |> Date.add(-days)
{:ok, DateTimeRange.new!(first, last, site.timezone)}
end
defp parse_time_range(site, "month", date, _now) do

View File

@ -31,7 +31,7 @@ defmodule Plausible.Stats.Interval do
case period do
period when period in ["realtime", "30m"] -> "minute"
"day" -> "hour"
period when period in ["custom", "7d", "30d", "month"] -> "day"
period when period in ["custom", "7d", "28d", "30d", "90d", "month"] -> "day"
period when period in ["6mo", "12mo", "year"] -> "month"
end
end
@ -57,8 +57,10 @@ defmodule Plausible.Stats.Interval do
"realtime" => ["minute"],
"day" => ["minute", "hour"],
"7d" => ["hour", "day"],
"month" => ["day", "week"],
"28d" => ["day", "week"],
"30d" => ["day", "week"],
"90d" => ["day", "week", "month"],
"month" => ["day", "week"],
"6mo" => ["day", "week", "month"],
"12mo" => ["day", "week", "month"],
"year" => ["day", "week", "month"],

View File

@ -91,26 +91,18 @@ defmodule Plausible.Stats.Legacy.QueryBuilder do
struct!(query, period: "day", utc_time_range: datetime_range)
end
defp put_period(query, site, %{"period" => "7d"} = params) do
end_date = parse_single_date(query, params)
start_date = end_date |> Date.shift(day: -6)
defp put_period(query, site, %{"period" => period} = params)
when period in ["7d", "28d", "30d", "90d"] do
{days, "d"} = Integer.parse(period)
end_date = parse_single_date(query, params) |> Date.shift(day: -1)
start_date = end_date |> Date.shift(day: 1 - days)
datetime_range =
DateTimeRange.new!(start_date, end_date, site.timezone)
|> DateTimeRange.to_timezone("Etc/UTC")
struct!(query, period: "7d", utc_time_range: datetime_range)
end
defp put_period(query, site, %{"period" => "30d"} = params) do
end_date = parse_single_date(query, params)
start_date = end_date |> Date.shift(day: -30)
datetime_range =
DateTimeRange.new!(start_date, end_date, site.timezone)
|> DateTimeRange.to_timezone("Etc/UTC")
struct!(query, period: "30d", utc_time_range: datetime_range)
struct!(query, period: period, utc_time_range: datetime_range)
end
defp put_period(query, site, %{"period" => "month"} = params) do

View File

@ -64,7 +64,8 @@ defmodule Plausible.Workers.SendEmailReport do
last_month =
DateTime.now!(site.timezone)
|> DateTime.shift(month: -1)
|> Timex.beginning_of_month()
|> DateTime.to_date()
|> Date.beginning_of_month()
|> Date.to_iso8601()
query = Query.from(site, %{"period" => "month", "date" => last_month})
@ -73,9 +74,18 @@ defmodule Plausible.Workers.SendEmailReport do
end
defp put_last_week_query(%{site: site} = assigns) do
today = DateTime.now!(site.timezone) |> DateTime.to_date()
date = Date.shift(today, week: -1) |> Timex.end_of_week() |> Date.to_iso8601()
query = Query.from(site, %{"period" => "7d", "date" => date})
# In production, evaluating and sending the date param to `Query.from`
# is redundant since the default value is today for `site.timezone` and
# weekly reports are always sent on Monday morning. However, this makes
# it easier to test - no need for a `now` argument.
date_param =
site.timezone
|> DateTime.now!()
|> DateTime.to_date()
|> Date.beginning_of_week()
|> Date.to_iso8601()
query = Query.from(site, %{"period" => "7d", "date" => date_param})
Map.put(assigns, :query, query)
end

View File

@ -197,10 +197,18 @@
"const": "7d",
"description": "Last 7 days relative to today"
},
{
"const": "28d",
"description": "Last 28 days relative to today"
},
{
"const": "30d",
"description": "Last 30 days relative to today"
},
{
"const": "90d",
"description": "Last 90 days relative to today"
},
{
"const": "month",
"description": "Current calendar month"

View File

@ -173,8 +173,8 @@ defmodule Plausible.Stats.ComparisonsTest do
comparison_query = Comparisons.get_comparison_query(query)
assert comparison_query.utc_time_range.first == ~U[2019-12-30 00:00:00Z]
assert comparison_query.utc_time_range.last == ~U[2020-01-05 23:59:59Z]
assert comparison_query.utc_time_range.first == ~U[2019-12-29 00:00:00Z]
assert comparison_query.utc_time_range.last == ~U[2020-01-04 23:59:59Z]
assert date_range_length(comparison_query) == 7
end
@ -182,7 +182,7 @@ defmodule Plausible.Stats.ComparisonsTest do
query =
Query.from(site, %{
"period" => "7d",
"date" => "2021-03-03",
"date" => "2021-03-04",
"comparison" => "year_over_year"
})
@ -204,8 +204,8 @@ defmodule Plausible.Stats.ComparisonsTest do
comparison_query = Comparisons.get_comparison_query(query)
assert comparison_query.utc_time_range.first == ~U[2020-11-19 00:00:00Z]
assert comparison_query.utc_time_range.last == ~U[2020-11-25 23:59:59Z]
assert comparison_query.utc_time_range.first == ~U[2020-11-18 00:00:00Z]
assert comparison_query.utc_time_range.last == ~U[2020-11-24 23:59:59Z]
assert date_range_length(comparison_query) == 7
end
end

View File

@ -28,9 +28,11 @@ defmodule Plausible.Stats.IntervalTest do
assert valid_by_period(site: site) == %{
"realtime" => ["minute"],
"day" => ["minute", "hour"],
"7d" => ["hour", "day"],
"month" => ["day", "week"],
"7d" => ["hour", "day"],
"28d" => ["day", "week"],
"30d" => ["day", "week"],
"90d" => ["day", "week", "month"],
"6mo" => ["day", "week", "month"],
"12mo" => ["day", "week", "month"],
"year" => ["day", "week", "month"],
@ -45,9 +47,11 @@ defmodule Plausible.Stats.IntervalTest do
assert valid_by_period(site: site) == %{
"realtime" => ["minute"],
"day" => ["minute", "hour"],
"7d" => ["hour", "day"],
"month" => ["day", "week"],
"7d" => ["hour", "day"],
"28d" => ["day", "week"],
"30d" => ["day", "week"],
"90d" => ["day", "week", "month"],
"6mo" => ["day", "week", "month"],
"12mo" => ["day", "week", "month"],
"year" => ["day", "week", "month"],
@ -63,9 +67,11 @@ defmodule Plausible.Stats.IntervalTest do
assert valid_by_period(site: site, from: ago_13m, to: Date.utc_today()) == %{
"realtime" => ["minute"],
"day" => ["minute", "hour"],
"7d" => ["hour", "day"],
"month" => ["day", "week"],
"7d" => ["hour", "day"],
"28d" => ["day", "week"],
"30d" => ["day", "week"],
"90d" => ["day", "week", "month"],
"6mo" => ["day", "week", "month"],
"12mo" => ["day", "week", "month"],
"year" => ["day", "week", "month"],

View File

@ -24,12 +24,12 @@ defmodule Plausible.Stats.Filters.QueryParserTest do
last: DateTime.new!(~D[2021-05-05], ~T[23:59:59], "Etc/UTC")
}
@date_range_7d %DateTimeRange{
first: DateTime.new!(~D[2021-04-29], ~T[00:00:00], "Etc/UTC"),
last: DateTime.new!(~D[2021-05-05], ~T[23:59:59], "Etc/UTC")
first: DateTime.new!(~D[2021-04-28], ~T[00:00:00], "Etc/UTC"),
last: DateTime.new!(~D[2021-05-04], ~T[23:59:59], "Etc/UTC")
}
@date_range_30d %DateTimeRange{
first: DateTime.new!(~D[2021-04-05], ~T[00:00:00], "Etc/UTC"),
last: DateTime.new!(~D[2021-05-05], ~T[23:59:59], "Etc/UTC")
last: DateTime.new!(~D[2021-05-04], ~T[23:59:59], "Etc/UTC")
}
@date_range_month %DateTimeRange{
first: DateTime.new!(~D[2021-05-01], ~T[00:00:00], "Etc/UTC"),
@ -988,7 +988,7 @@ defmodule Plausible.Stats.Filters.QueryParserTest do
"metrics" => ["visitors"],
"date_range" => "all",
"include" => %{
"comparisons" => %{"mode" => "custom", "date_range" => ["2021-04-05", "2021-05-05"]}
"comparisons" => %{"mode" => "custom", "date_range" => ["2021-04-05", "2021-05-04"]}
}
}
|> check_success(

View File

@ -883,7 +883,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => "visit:referrer==**a.com**"
@ -1506,7 +1506,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => "event:page==/en/**"
@ -1523,7 +1523,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => "event:page!=/en/**"
@ -1541,7 +1541,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => "event:page==/en/**|/pl/**"
@ -1559,7 +1559,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => "event:page==**post\\|1|/something-else"
@ -1579,7 +1579,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "pageviews",
"filters" => "visit:country==EE"
@ -1672,7 +1672,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
insert(:goal, %{site: site, event_name: "Signup"})
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "conversion_rate",
"filters" => "event:goal==Signup"
@ -1695,7 +1695,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
insert(:goal, %{site: site, event_name: "Signup"})
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "conversion_rate,visitors,events",
"filters" => "event:goal==Signup;event:props:author==Uku"
@ -1724,7 +1724,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
insert(:goal, %{site: site, event_name: "Signup"})
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "conversion_rate,visitors,events",
"filters" => "visit:browser==Firefox;event:goal==Signup"
@ -1754,7 +1754,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
insert(:goal, %{site: site, event_name: "Signup"})
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "conversion_rate,visitors,events",
"filters" => "event:page==/this;event:goal==Signup"
@ -1796,7 +1796,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => [
@ -1865,7 +1865,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => [
@ -1886,7 +1886,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => [
@ -1918,7 +1918,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => [
@ -1951,7 +1951,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => [
@ -1983,7 +1983,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => [
@ -2015,7 +2015,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.AggregateTest do
])
conn =
get(conn, "/api/v1/stats/aggregate", %{
get(conn, "/api/v1/stats/aggregate?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors",
"filters" => [

View File

@ -1666,7 +1666,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
])
conn =
get(conn, "/api/v1/stats/breakdown", %{
get(conn, "/api/v1/stats/breakdown?period=day", %{
"site_id" => site.domain,
"metrics" => "visitors,pageviews",
"property" => "event:goal"
@ -2387,7 +2387,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.BreakdownTest do
])
conn =
get(conn, "/api/v1/stats/breakdown", %{
get(conn, "/api/v1/stats/breakdown?period=day", %{
"site_id" => site.domain,
"filters" => "visit:browser != Chrome",
"property" => "visit:browser"

View File

@ -113,6 +113,128 @@ defmodule PlausibleWeb.Api.ExternalStatsController.QueryComparisonsTest do
]
end
test "timeseries last 28d period compares the same period with and without match_day_of_week=true",
%{
conn: conn,
site: site
} do
today = ~D[2021-06-10]
make_request = fn match_day_of_week ->
conn
|> post("/api/v2/query-internal-test", %{
"site_id" => site.domain,
"metrics" => ["visitors"],
"date_range" => "28d",
"date" => Date.to_iso8601(today),
"dimensions" => ["time"],
"include" => %{
"time_labels" => true,
"comparisons" => %{
"mode" => "previous_period",
"match_day_of_week" => match_day_of_week
}
}
})
|> json_response(200)
end
assert %{"results" => results1} = make_request.(false)
assert %{"results" => results2} = make_request.(true)
assert results1 == results2
expected_first_date = today |> Date.shift(day: -28) |> Date.to_iso8601()
expected_last_date = today |> Date.shift(day: -1) |> Date.to_iso8601()
expected_comparison_first_date = today |> Date.shift(day: -56) |> Date.to_iso8601()
expected_comparison_last_date = today |> Date.shift(day: -29) |> Date.to_iso8601()
assert %{
"dimensions" => [actual_first_date],
"comparison" => %{
"dimensions" => [actual_comparison_first_date]
}
} = List.first(results1)
assert %{
"dimensions" => [actual_last_date],
"comparison" => %{
"dimensions" => [actual_comparison_last_date]
}
} = List.last(results1)
assert actual_first_date == expected_first_date
assert actual_last_date == expected_last_date
assert actual_comparison_first_date == expected_comparison_first_date
assert actual_comparison_last_date == expected_comparison_last_date
end
test "timeseries last 90d period in year_over_year comparison", %{
conn: conn,
site: site
} do
populate_stats(site, [
build(:pageview, timestamp: ~N[2021-04-01 00:00:00]),
build(:pageview, timestamp: ~N[2021-04-01 00:00:00]),
build(:pageview, timestamp: ~N[2021-04-05 00:00:00]),
build(:pageview, timestamp: ~N[2021-04-05 00:00:00]),
build(:pageview, timestamp: ~N[2021-06-29 00:00:00]),
build(:pageview, timestamp: ~N[2022-04-01 00:00:00]),
build(:pageview, timestamp: ~N[2022-04-05 00:00:00]),
build(:pageview, timestamp: ~N[2022-06-29 00:00:00]),
build(:pageview, timestamp: ~N[2022-06-30 00:00:00])
])
conn =
post(conn, "/api/v2/query-internal-test", %{
"site_id" => site.domain,
"metrics" => ["visitors"],
"date_range" => "90d",
"date" => "2022-06-30",
"dimensions" => ["time:day"],
"include" => %{
"time_labels" => true,
"comparisons" => %{"mode" => "year_over_year"}
}
})
assert %{
"results" => results,
"meta" => %{"time_labels" => time_labels}
} = json_response(conn, 200)
assert "2022-04-01" = List.first(time_labels)
assert "2022-04-05" = Enum.at(time_labels, 4)
assert "2022-06-29" = List.last(time_labels)
assert %{
"dimensions" => ["2022-04-01"],
"metrics" => [1],
"comparison" => %{
"dimensions" => ["2021-04-01"],
"metrics" => [2]
}
} = Enum.find(results, &(&1["dimensions"] == ["2022-04-01"]))
assert %{
"dimensions" => ["2022-04-05"],
"metrics" => [1],
"comparison" => %{
"dimensions" => ["2021-04-05"],
"metrics" => [2]
}
} = Enum.find(results, &(&1["dimensions"] == ["2022-04-05"]))
assert %{
"dimensions" => ["2022-06-29"],
"metrics" => [1],
"comparison" => %{
"dimensions" => ["2021-06-29"],
"metrics" => [1]
}
} = Enum.find(results, &(&1["dimensions"] == ["2022-06-29"]))
end
test "dimensional comparison with low limit", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview, browser: "Firefox", timestamp: ~N[2021-01-01 00:00:00]),

View File

@ -338,7 +338,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
get(conn, "/api/v1/stats/timeseries", %{
"site_id" => site.domain,
"period" => "7d",
"date" => "2021-01-07"
"date" => "2021-01-08"
})
assert json_response(conn, 200) == %{
@ -1240,7 +1240,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
"metrics" => "conversion_rate",
"filters" => "event:goal==Signup",
"period" => "7d",
"date" => "2021-01-10"
"date" => "2021-01-11"
})
assert [first, second | _] = json_response(conn, 200)["results"]
@ -1290,7 +1290,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
"metrics" => "conversion_rate",
"filters" => "event:goal==Signup;event:props:author==Teet",
"period" => "7d",
"date" => "2021-01-10"
"date" => "2021-01-11"
})
[first | _] = json_response(conn, 200)["results"]
@ -1329,7 +1329,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
"metrics" => "conversion_rate",
"filters" => "event:goal==Signup;event:page==/yes",
"period" => "7d",
"date" => "2021-01-10"
"date" => "2021-01-11"
})
[first | _] = json_response(conn, 200)["results"]
@ -1368,7 +1368,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
"metrics" => "conversion_rate",
"filters" => "event:goal==Signup;visit:device==Mobile",
"period" => "7d",
"date" => "2021-01-10"
"date" => "2021-01-11"
})
[first | _] = json_response(conn, 200)["results"]
@ -1414,7 +1414,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
"site_id" => site.domain,
"period" => "7d",
"metrics" => "pageviews,visits,views_per_visit",
"date" => "2021-01-07"
"date" => "2021-01-08"
})
assert json_response(conn, 200) == %{
@ -1477,7 +1477,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
"site_id" => site.domain,
"period" => "7d",
"metrics" => "events",
"date" => "2021-01-07"
"date" => "2021-01-08"
})
assert json_response(conn, 200) == %{
@ -1545,7 +1545,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
"site_id" => site.domain,
"period" => "7d",
"metrics" => "views_per_visit",
"date" => "2021-01-07"
"date" => "2021-01-08"
})
assert json_response(conn, 200) == %{
@ -1579,7 +1579,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
"site_id" => site.domain,
"period" => "7d",
"metrics" => "events",
"date" => "2021-01-07",
"date" => "2021-01-08",
"with_imported" => "true"
})
@ -1615,7 +1615,7 @@ defmodule PlausibleWeb.Api.ExternalStatsController.TimeseriesTest do
"site_id" => site.domain,
"period" => "7d",
"metrics" => "events",
"date" => "2021-01-07",
"date" => "2021-01-08",
"with_imported" => "true",
"filters" => "event:props:package==large"
})

View File

@ -204,7 +204,7 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/browsers?period=7d&date=2021-01-13&comparison=previous_period"
"/api/stats/#{site.domain}/browsers?period=7d&date=2021-01-14&comparison=previous_period"
)
assert json_response(conn, 200)["results"] == [
@ -267,8 +267,8 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do
]
assert json_response(conn, 200)["meta"] == %{
"date_range_label" => "7 Jan - 13 Jan 2021",
"comparison_date_range_label" => "31 Dec 2020 - 6 Jan 2021"
"date_range_label" => "6 Jan - 12 Jan 2021",
"comparison_date_range_label" => "30 Dec 2020 - 5 Jan 2021"
}
end
end
@ -367,7 +367,10 @@ defmodule PlausibleWeb.Api.StatsController.BrowsersTest do
filters = Jason.encode!([[:is, "visit:browser", ["Chrome"]]])
conn =
get(conn, "/api/stats/#{site.domain}/browser-versions?filters=#{filters}&detailed=true")
get(
conn,
"/api/stats/#{site.domain}/browser-versions?filters=#{filters}&detailed=true&period=day"
)
assert json_response(conn, 200)["results"] == [
%{

View File

@ -147,6 +147,46 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
assert Enum.sum(plot) == 2
end
test "displays visitors for last 28d", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview, timestamp: ~N[2021-01-01 00:00:00]),
build(:pageview, timestamp: ~N[2021-01-28 00:00:00])
])
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=28d&date=2021-01-29&metric=visitors"
)
assert %{"plot" => plot} = json_response(conn, 200)
assert Enum.count(plot) == 28
assert List.first(plot) == 1
assert List.last(plot) == 1
assert Enum.sum(plot) == 2
end
test "displays visitors for last 90d", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview, timestamp: ~N[2021-01-16 00:00:00]),
build(:pageview, timestamp: ~N[2021-04-15 00:00:00])
])
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=90d&date=2021-04-16&metric=visitors"
)
assert %{"plot" => plot} = json_response(conn, 200)
assert Enum.count(plot) == 90
assert List.first(plot) == 1
assert List.last(plot) == 1
assert Enum.sum(plot) == 2
end
test "displays visitors for a month with imported data", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview, timestamp: ~N[2021-01-01 00:00:00]),
@ -373,7 +413,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
assert %{"labels" => labels} = json_response(conn, 200)
{:ok, first} = Timex.today() |> Timex.shift(days: -30) |> Timex.format("{ISOdate}")
{:ok, last} = Timex.today() |> Timex.format("{ISOdate}")
{:ok, last} = Timex.today() |> Timex.shift(days: -1) |> Timex.format("{ISOdate}")
assert List.first(labels) == first
assert List.last(labels) == last
end
@ -382,8 +422,8 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
conn = get(conn, "/api/stats/#{site.domain}/main-graph?period=7d&metric=visitors")
assert %{"labels" => labels} = json_response(conn, 200)
{:ok, first} = Timex.today() |> Timex.shift(days: -6) |> Timex.format("{ISOdate}")
{:ok, last} = Timex.today() |> Timex.format("{ISOdate}")
{:ok, first} = Timex.today() |> Timex.shift(days: -7) |> Timex.format("{ISOdate}")
{:ok, last} = Timex.today() |> Timex.shift(days: -1) |> Timex.format("{ISOdate}")
assert List.first(labels) == first
assert List.last(labels) == last
end
@ -553,7 +593,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=7d&date=2021-01-07&metric=visitors&interval=day"
"/api/stats/#{site.domain}/main-graph?period=7d&date=2021-01-08&metric=visitors&interval=day"
)
assert %{"plot" => plot} = json_response(conn, 200)
@ -626,7 +666,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=7d&date=2020-01-07&metric=scroll_depth&filters=#{filters}"
"/api/stats/#{site.domain}/main-graph?period=7d&date=2020-01-08&metric=scroll_depth&filters=#{filters}"
)
assert %{"plot" => plot} = json_response(conn, 200)
@ -671,7 +711,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=7d&date=2020-01-07&metric=scroll_depth&filters=#{filters}&with_imported=true"
"/api/stats/#{site.domain}/main-graph?period=7d&date=2020-01-08&metric=scroll_depth&filters=#{filters}&with_imported=true"
)
assert %{"plot" => plot} = json_response(conn, 200)
@ -1135,7 +1175,8 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
}
end
test "shows perfect week-split range on week scale with full week indicators", %{
test "shows perfect week-split range on week scale with full week indicators for custom period",
%{
conn: conn,
site: site
} do
@ -1168,7 +1209,52 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
}
end
test "shows imperfect month-split period on month scale with full month indicators", %{
test "shows imperfect week-split for last 28d with full week indicators", %{
conn: conn,
site: site
} do
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=28d&metric=visitors&interval=week&date=2021-10-30"
)
assert %{"labels" => labels, "full_intervals" => full_intervals} = json_response(conn, 200)
assert labels == ["2021-10-02", "2021-10-04", "2021-10-11", "2021-10-18", "2021-10-25"]
assert full_intervals == %{
"2021-10-02" => false,
"2021-10-04" => true,
"2021-10-11" => true,
"2021-10-18" => true,
"2021-10-25" => false
}
end
test "shows perfect week-split for last 28d with full week indicators", %{
conn: conn,
site: site
} do
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=28d&date=2021-02-08&metric=visitors&interval=week"
)
assert %{"labels" => labels, "full_intervals" => full_intervals} = json_response(conn, 200)
assert labels == ["2021-01-11", "2021-01-18", "2021-01-25", "2021-02-01"]
assert full_intervals == %{
"2021-01-11" => true,
"2021-01-18" => true,
"2021-01-25" => true,
"2021-02-01" => true
}
end
test "shows imperfect month-split for custom period with full month indicators", %{
conn: conn,
site: site
} do
@ -1190,6 +1276,49 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
}
end
test "shows imperfect month-split for last 90d with full month indicators", %{
conn: conn,
site: site
} do
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=90d&metric=visitors&interval=month&date=2021-12-13"
)
assert %{"labels" => labels, "full_intervals" => full_intervals} = json_response(conn, 200)
assert labels == ["2021-09-01", "2021-10-01", "2021-11-01", "2021-12-01"]
assert full_intervals == %{
"2021-09-01" => false,
"2021-10-01" => true,
"2021-11-01" => true,
"2021-12-01" => false
}
end
test "shows half-perfect month-split for last 90d with full month indicators", %{
conn: conn,
site: site
} do
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=90d&metric=visitors&interval=month&date=2021-12-01"
)
assert %{"labels" => labels, "full_intervals" => full_intervals} = json_response(conn, 200)
assert labels == ["2021-09-01", "2021-10-01", "2021-11-01"]
assert full_intervals == %{
"2021-09-01" => false,
"2021-10-01" => true,
"2021-11-01" => true
}
end
test "returns stats for a day with a minute interval", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview, timestamp: ~N[2023-03-01 12:00:00])
@ -1227,12 +1356,12 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
json_response(conn, 200)
{:ok, first} = Timex.today() |> Timex.shift(days: -30) |> Timex.format("{ISOdate}")
{:ok, last} = Timex.today() |> Timex.format("{ISOdate}")
{:ok, last} = Timex.today() |> Timex.shift(days: -1) |> Timex.format("{ISOdate}")
assert List.first(labels) == first
assert List.last(labels) == last
{:ok, first} = Timex.today() |> Timex.shift(days: -61) |> Timex.format("{ISOdate}")
{:ok, first} = Timex.today() |> Timex.shift(days: -60) |> Timex.format("{ISOdate}")
{:ok, last} = Timex.today() |> Timex.shift(days: -31) |> Timex.format("{ISOdate}")
assert List.first(comparison_labels) == first
@ -1375,7 +1504,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=7d&date=2021-01-14&comparison=previous_period&metric=conversion_rate&filters=#{filters}"
"/api/stats/#{site.domain}/main-graph?period=7d&date=2021-01-15&comparison=previous_period&metric=conversion_rate&filters=#{filters}"
)
assert %{"plot" => this_week_plot, "comparison_plot" => last_week_plot} =
@ -1511,7 +1640,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=7d&date=2021-01-14&metric=total_revenue&filters=#{filters}&comparison=previous_period"
"/api/stats/#{site.domain}/main-graph?period=7d&date=2021-01-15&metric=total_revenue&filters=#{filters}&comparison=previous_period"
)
assert %{"plot" => plot, "comparison_plot" => prev} = json_response(conn, 200)
@ -1669,7 +1798,7 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=7d&date=2021-01-14&metric=average_revenue&filters=#{filters}&comparison=previous_period"
"/api/stats/#{site.domain}/main-graph?period=7d&date=2021-01-15&metric=average_revenue&filters=#{filters}&comparison=previous_period"
)
assert %{"plot" => plot, "comparison_plot" => prev} = json_response(conn, 200)
@ -1733,5 +1862,23 @@ defmodule PlausibleWeb.Api.StatsController.MainGraphTest do
refute present_index
end
for period <- ["7d", "28d", "30d", "90d"] do
test "#{period} period does not include today", %{conn: conn, site: site} do
today = "2021-01-01"
yesterday = "2020-12-31"
conn =
get(
conn,
"/api/stats/#{site.domain}/main-graph?period=#{unquote(period)}&date=#{today}&metric=pageviews"
)
assert %{"labels" => labels, "present_index" => present_index} = json_response(conn, 200)
refute present_index
assert List.last(labels) == yesterday
end
end
end
end

View File

@ -277,7 +277,7 @@ defmodule PlausibleWeb.Api.StatsController.OperatingSystemsTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/operating-system-versions?filters=#{filters}&detailed=true"
"/api/stats/#{site.domain}/operating-system-versions?filters=#{filters}&detailed=true&period=day"
)
assert json_response(conn, 200)["results"] == [

View File

@ -32,7 +32,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do
build(:pageview)
])
conn = get(conn, "/api/stats/#{site.domain}/sources")
conn = get(conn, "/api/stats/#{site.domain}/sources?period=day")
assert json_response(conn, 200)["results"] == [
%{"name" => "Google", "visitors" => 3},
@ -273,14 +273,14 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do
)
])
conn1 = get(conn, "/api/stats/#{site.domain}/sources")
conn1 = get(conn, "/api/stats/#{site.domain}/sources?period=day")
assert json_response(conn1, 200)["results"] == [
%{"name" => "Google", "visitors" => 2},
%{"name" => "DuckDuckGo", "visitors" => 1}
]
conn2 = get(conn, "/api/stats/#{site.domain}/sources?with_imported=true")
conn2 = get(conn, "/api/stats/#{site.domain}/sources?period=day&with_imported=true")
assert json_response(conn2, 200)["results"] == [
%{"name" => "Google", "visitors" => 4},
@ -466,13 +466,17 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do
)
])
conn1 = get(conn, "/api/stats/#{site.domain}/sources?limit=1&page=2")
conn1 = get(conn, "/api/stats/#{site.domain}/sources?period=day&limit=1&page=2")
assert json_response(conn1, 200)["results"] == [
%{"name" => "DuckDuckGo", "visitors" => 1}
]
conn2 = get(conn, "/api/stats/#{site.domain}/sources?limit=1&page=2&with_imported=true")
conn2 =
get(
conn,
"/api/stats/#{site.domain}/sources?period=day&limit=1&page=2&with_imported=true"
)
assert json_response(conn2, 200)["results"] == [
%{"name" => "Google", "visitors" => 2}
@ -496,7 +500,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do
])
filters = Jason.encode!([[:is, "event:page", ["/page1"]]])
conn = get(conn, "/api/stats/#{site.domain}/sources?filters=#{filters}")
conn = get(conn, "/api/stats/#{site.domain}/sources?period=day&filters=#{filters}")
assert json_response(conn, 200)["results"] == [
%{"name" => "Google", "visitors" => 2},
@ -521,7 +525,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do
])
filters = Jason.encode!([[:is, "event:page", ["/page1"]]])
conn = get(conn, "/api/stats/#{site.domain}/sources?filters=#{filters}")
conn = get(conn, "/api/stats/#{site.domain}/sources?period=day&filters=#{filters}")
assert json_response(conn, 200)["results"] == [
%{"name" => "Google", "visitors" => 2},
@ -537,7 +541,7 @@ defmodule PlausibleWeb.Api.StatsController.SourcesTest do
])
order_by = Jason.encode!([["visit:source", "desc"]])
conn = get(conn, "/api/stats/#{site.domain}/sources?order_by=#{order_by}")
conn = get(conn, "/api/stats/#{site.domain}/sources?order_by=#{order_by}&period=day")
assert json_response(conn, 200)["results"] == [
%{"name" => "C", "visitors" => 1},

View File

@ -139,7 +139,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/suggestions/region?q=Har"
"/api/stats/#{site.domain}/suggestions/region?period=day&q=Har"
)
assert json_response(conn, 200) == [%{"value" => "EE-37", "label" => "Harjumaa"}]
@ -164,7 +164,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/suggestions/city?q=Kär"
"/api/stats/#{site.domain}/suggestions/city?period=day&q=Kär"
)
assert json_response(conn, 200) == [%{"value" => 591_632, "label" => "Kärdla"}]
@ -291,7 +291,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn1,
"/api/stats/#{site.domain}/suggestions/hostname?q=alice"
"/api/stats/#{site.domain}/suggestions/hostname?period=day&q=alice"
)
assert json_response(conn, 200) == [
@ -301,7 +301,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn1,
"/api/stats/#{site.domain}/suggestions/hostname?q=host"
"/api/stats/#{site.domain}/suggestions/hostname?period=day&q=host"
)
suggestions = json_response(conn, 200)
@ -344,7 +344,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn1,
"/api/stats/#{site.domain}/suggestions/hostname?q=host"
"/api/stats/#{site.domain}/suggestions/hostname?period=day&q=host"
)
results = json_response(conn, 200)
@ -360,7 +360,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn1,
"/api/stats/#{site.domain}/suggestions/hostname?q=dave"
"/api/stats/#{site.domain}/suggestions/hostname?period=day&q=dave"
)
assert json_response(conn, 200) == []
@ -368,7 +368,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn1,
"/api/stats/#{site.domain}/suggestions/hostname?q=rogue"
"/api/stats/#{site.domain}/suggestions/hostname?period=day&q=rogue"
)
assert json_response(conn, 200) == [
@ -820,7 +820,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/suggestions/country?filters=#{filters}&q=&with_imported=true"
"/api/stats/#{site.domain}/suggestions/country?period=day&filters=#{filters}&q=&with_imported=true"
)
assert json_response(conn, 200) == [%{"value" => "EE", "label" => "Estonia"}]
@ -880,7 +880,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/suggestions/region?q=#{unquote(q)}&with_imported=true"
"/api/stats/#{site.domain}/suggestions/region?period=day&q=#{unquote(q)}&with_imported=true"
)
assert json_response(conn, 200) == [
@ -908,7 +908,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn1 =
get(
conn,
"/api/stats/#{site.domain}/suggestions/region?q=&with_imported=true"
"/api/stats/#{site.domain}/suggestions/region?period=day&q=&with_imported=true"
)
assert json_response(conn1, 200) == [
@ -919,7 +919,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn2 =
get(
conn,
"/api/stats/#{site.domain}/suggestions/region?q=H&with_imported=true"
"/api/stats/#{site.domain}/suggestions/region?period=day&q=H&with_imported=true"
)
assert json_response(conn2, 200) == [
@ -948,7 +948,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/suggestions/region?filters=#{filters}&q=&with_imported=true"
"/api/stats/#{site.domain}/suggestions/region?period=day&filters=#{filters}&q=&with_imported=true"
)
assert json_response(conn, 200) == [%{"value" => "EE-39", "label" => "Hiiumaa"}]
@ -1020,7 +1020,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/suggestions/city?q=#{unquote(q)}&with_imported=true"
"/api/stats/#{site.domain}/suggestions/city?period=day&q=#{unquote(q)}&with_imported=true"
)
assert json_response(conn, 200) == [
@ -1050,7 +1050,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn =
get(
conn,
"/api/stats/#{site.domain}/suggestions/city?filters=#{filters}&q=&with_imported=true"
"/api/stats/#{site.domain}/suggestions/city?period=day&filters=#{filters}&q=&with_imported=true"
)
assert json_response(conn, 200) == [%{"value" => 591_632, "label" => "Kärdla"}]

View File

@ -345,7 +345,7 @@ defmodule PlausibleWeb.StatsControllerTest do
pages =
conn
|> get("/#{site.domain}/export?date=2020-01-01")
|> get("/#{site.domain}/export?period=day&date=2020-01-01")
|> response(200)
|> unzip_and_parse_csv(~c"pages.csv")
@ -411,7 +411,10 @@ defmodule PlausibleWeb.StatsControllerTest do
test "exports data in zipped csvs", %{conn: conn, site: site} do
populate_exported_stats(site)
conn = get(conn, "/" <> site.domain <> "/export?date=2021-10-20")
conn =
get(conn, "/" <> site.domain <> "/export?period=custom&from=2021-09-20&to=2021-10-20")
assert_zip(conn, "30d")
end
@ -459,7 +462,10 @@ defmodule PlausibleWeb.StatsControllerTest do
visitors =
conn
|> get("/" <> site.domain <> "/export?date=2021-10-20&period=30d&interval=week")
|> get(
"/" <>
site.domain <> "/export?period=custom&from=2021-09-20&to=2021-10-20&interval=week"
)
|> response(200)
|> unzip_and_parse_csv(~c"visitors.csv")
@ -500,7 +506,7 @@ defmodule PlausibleWeb.StatsControllerTest do
os_versions =
conn
|> get("/#{site.domain}/export")
|> get("/#{site.domain}/export?period=day")
|> response(200)
|> unzip_and_parse_csv(~c"operating_system_versions.csv")
@ -550,7 +556,9 @@ defmodule PlausibleWeb.StatsControllerTest do
)
])
conn = get(conn, "/#{site.domain}/export?with_imported=true")
tomorrow = Date.utc_today() |> Date.add(1) |> Date.to_iso8601()
conn = get(conn, "/#{site.domain}/export?date=#{tomorrow}&with_imported=true")
assert response = response(conn, 200)
{:ok, zip} = :zip.unzip(response, [:memory])
@ -750,7 +758,14 @@ defmodule PlausibleWeb.StatsControllerTest do
link = insert(:shared_link, site: site)
populate_exported_stats(site)
conn = get(conn, "/" <> site.domain <> "/export?auth=#{link.slug}&date=2021-10-20")
conn =
get(
conn,
"/" <>
site.domain <> "/export?auth=#{link.slug}&period=custom&from=2021-09-20&to=2021-10-20"
)
assert_zip(conn, "30d")
end
end
@ -772,7 +787,13 @@ defmodule PlausibleWeb.StatsControllerTest do
populate_exported_stats(site)
filters = Jason.encode!([[:is, "event:page", ["/some-other-page"]]])
conn = get(conn, "/#{site.domain}/export?date=2021-10-20&filters=#{filters}")
conn =
get(
conn,
"/#{site.domain}/export?period=custom&from=2021-09-20&to=2021-10-20&filters=#{filters}"
)
assert_zip(conn, "30d-filter-path")
end
@ -805,7 +826,7 @@ defmodule PlausibleWeb.StatsControllerTest do
pages =
conn
|> get("/#{site.domain}/export?date=2020-01-07&period=7d&filters=#{filters}")
|> get("/#{site.domain}/export?date=2020-01-08&period=7d&filters=#{filters}")
|> response(200)
|> unzip_and_parse_csv(~c"visitors.csv")
@ -973,7 +994,13 @@ defmodule PlausibleWeb.StatsControllerTest do
test "exports goal-filtered data in zipped csvs", %{conn: conn, site: site} do
populate_exported_stats(site)
filters = Jason.encode!([[:is, "event:goal", ["Signup"]]])
conn = get(conn, "/#{site.domain}/export?date=2021-10-20&filters=#{filters}")
conn =
get(
conn,
"/#{site.domain}/export?period=custom&from=2021-09-20&to=2021-10-20&filters=#{filters}"
)
assert_zip(conn, "30d-filter-goal")
end
@ -1051,7 +1078,7 @@ defmodule PlausibleWeb.StatsControllerTest do
os_versions =
conn
|> get("/#{site.domain}/export?filters=#{filters}")
|> get("/#{site.domain}/export?period=day&filters=#{filters}")
|> response(200)
|> unzip_and_parse_csv(~c"operating_system_versions.csv")