Skip to content

Commit 88f82af

Browse files
committed
fix: app crash when rill time syntax is used in comparison (#9072)
* fix: app crash when rill time syntax is used in comparison * Fix isNewSyntax and add more tests
1 parent 9bc6e55 commit 88f82af

5 files changed

Lines changed: 82 additions & 9 deletions

File tree

web-common/src/features/dashboards/stores/test-data/store-mutations.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ import {
4848
RandomPublishers,
4949
} from "@rilldata/web-common/features/dashboards/stores/test-data/random";
5050
import { TDDChart } from "@rilldata/web-common/features/dashboards/time-dimension-details/types";
51-
import { TimeRangePreset } from "@rilldata/web-common/lib/time/types";
51+
import {
52+
type DashboardTimeControls,
53+
type TimeRange,
54+
TimeRangePreset,
55+
} from "@rilldata/web-common/lib/time/types";
5256
import { asyncWait } from "@rilldata/web-common/lib/waitUtils.ts";
5357
import { DashboardState_LeaderboardSortType } from "@rilldata/web-common/proto/gen/rill/ui/v1/dashboard_pb";
5458
import { V1TimeGrain } from "@rilldata/web-common/runtime-client";
@@ -136,23 +140,23 @@ export const AD_BIDS_CLEAR_FILTERS: TestDashboardMutation = (mut) =>
136140
export const AD_BIDS_SET_P7D_TIME_RANGE_FILTER: TestDashboardMutation = () =>
137141
metricsExplorerStore.selectTimeRange(
138142
AD_BIDS_EXPLORE_NAME,
139-
{ name: TimeRangePreset.LAST_7_DAYS } as any,
143+
{ name: TimeRangePreset.LAST_7_DAYS } as TimeRange,
140144
V1TimeGrain.TIME_GRAIN_DAY,
141145
undefined,
142146
AD_BIDS_METRICS_INIT,
143147
);
144148
export const AD_BIDS_SET_P4W_TIME_RANGE_FILTER: TestDashboardMutation = () =>
145149
metricsExplorerStore.selectTimeRange(
146150
AD_BIDS_EXPLORE_NAME,
147-
{ name: TimeRangePreset.LAST_4_WEEKS } as any,
151+
{ name: TimeRangePreset.LAST_4_WEEKS } as TimeRange,
148152
V1TimeGrain.TIME_GRAIN_WEEK,
149153
undefined,
150154
AD_BIDS_METRICS_INIT,
151155
);
152156
export const AD_BIDS_SET_ALL_TIME_RANGE_FILTER: TestDashboardMutation = () =>
153157
metricsExplorerStore.selectTimeRange(
154158
AD_BIDS_EXPLORE_NAME,
155-
{ name: TimeRangePreset.ALL_TIME } as any,
159+
{ name: TimeRangePreset.ALL_TIME } as TimeRange,
156160
V1TimeGrain.TIME_GRAIN_DAY,
157161
undefined,
158162
AD_BIDS_METRICS_INIT,
@@ -166,7 +170,7 @@ export const AD_BIDS_SET_PREVIOUS_PERIOD_COMPARE_TIME_RANGE_FILTER: TestDashboar
166170
metricsExplorerStore.displayTimeComparison(AD_BIDS_EXPLORE_NAME, true);
167171
metricsExplorerStore.setSelectedComparisonRange(
168172
AD_BIDS_EXPLORE_NAME,
169-
{ name: "rill-PP" } as any,
173+
{ name: "rill-PP" } as DashboardTimeControls,
170174
AD_BIDS_METRICS_INIT,
171175
);
172176
};
@@ -175,7 +179,16 @@ export const AD_BIDS_SET_PREVIOUS_WEEK_COMPARE_TIME_RANGE_FILTER: TestDashboardM
175179
metricsExplorerStore.displayTimeComparison(AD_BIDS_EXPLORE_NAME, true);
176180
metricsExplorerStore.setSelectedComparisonRange(
177181
AD_BIDS_EXPLORE_NAME,
178-
{ name: "rill-PW" } as any,
182+
{ name: "rill-PW" } as DashboardTimeControls,
183+
AD_BIDS_METRICS_INIT,
184+
);
185+
};
186+
export const AD_BIDS_SET_PREVIOUS_WEEK_RILL_TIME_COMPARE_TIME_RANGE_FILTER: TestDashboardMutation =
187+
() => {
188+
metricsExplorerStore.displayTimeComparison(AD_BIDS_EXPLORE_NAME, true);
189+
metricsExplorerStore.setSelectedComparisonRange(
190+
AD_BIDS_EXPLORE_NAME,
191+
{ name: "7D offset -7D" } as DashboardTimeControls,
179192
AD_BIDS_METRICS_INIT,
180193
);
181194
};

web-common/src/features/dashboards/url-state/time-ranges/parser.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ export function parseRillTime(rillTimeRange: string): RillTime {
1111
return rt;
1212
}
1313

14+
export function isNewRillTimeFormat(rillTime: string): boolean {
15+
try {
16+
const parser = parseRillTime(rillTime);
17+
return !parser.isOldFormat;
18+
} catch {
19+
return false;
20+
}
21+
}
22+
1423
export function validateRillTime(rillTime: string): Error | undefined {
1524
try {
1625
const parser = parseRillTime(rillTime);

web-common/src/features/dashboards/url-state/url-state-variations.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import {
4444
AD_BIDS_SET_PIVOT_ROW_LIMIT_UNLIMITED,
4545
AD_BIDS_SET_PREVIOUS_PERIOD_COMPARE_TIME_RANGE_FILTER,
4646
AD_BIDS_SET_PREVIOUS_WEEK_COMPARE_TIME_RANGE_FILTER,
47+
AD_BIDS_SET_PREVIOUS_WEEK_RILL_TIME_COMPARE_TIME_RANGE_FILTER,
4748
AD_BIDS_SET_PUBLISHER_COMPARE_DIMENSION,
4849
AD_BIDS_SET_TIME_DIMENSION_OFFSET,
4950
AD_BIDS_SET_TIME_DIMENSION_PRIMARY,
@@ -158,6 +159,13 @@ const TestCases: {
158159
expectedSearch:
159160
"tr=inf&tz=Asia%2FKathmandu&grain=day&measures=impressions&dims=publisher&sort_type=percent&sort_dir=ASC",
160161
},
162+
{
163+
title: "Time range with preset and ALL_TIME selected",
164+
mutations: [AD_BIDS_SET_PREVIOUS_WEEK_RILL_TIME_COMPARE_TIME_RANGE_FILTER],
165+
preset: AD_BIDS_PRESET,
166+
expectedSearch:
167+
"tr=P7D&tz=Asia%2FKathmandu&compare_tr=7D+offset+-7D&grain=day&measures=impressions&dims=publisher&sort_type=percent&sort_dir=ASC",
168+
},
161169

162170
{
163171
title: "Time range comparison without preset",

web-common/src/lib/time/comparisons/index.spec.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,47 @@ const periodicComparisonTests = [
9090
},
9191
];
9292

93+
const invalidComparisionTests = [
94+
{
95+
description: "should return undefined when comparison is invalid",
96+
input: {
97+
start: periodStart,
98+
end: periodEnd,
99+
comparison: "invalid" as TimeComparisonOption,
100+
},
101+
output: undefined,
102+
},
103+
{
104+
description: "should return undefined when comparison is new syntax",
105+
input: {
106+
start: periodStart,
107+
end: periodEnd,
108+
comparison: "7D as of latest/D-7D",
109+
},
110+
output: undefined,
111+
},
112+
{
113+
description:
114+
"should return undefined when comparison is new syntax using offset keyword",
115+
input: {
116+
start: periodStart,
117+
end: periodEnd,
118+
comparison: "7D as of latest/D offset -7D",
119+
},
120+
output: undefined,
121+
},
122+
];
123+
93124
const getComparisonIntervalTests = [
94125
...contiguousAndCustomComparisonRanges,
95126
...periodicComparisonTests,
127+
...invalidComparisionTests,
96128
];
97129

98130
describe("getComparisonInterval", () => {
99131
getComparisonIntervalTests.forEach((test) => {
100132
it(test.description, () => {
101133
const { start, end, comparison } = test.input;
102-
const { start: expectedStart, end: expectedEnd } = test.output;
103134
const interval = Interval.fromDateTimes(
104135
DateTime.fromJSDate(start, { zone: "UTC" }),
105136
DateTime.fromJSDate(end, { zone: "UTC" }),
@@ -110,6 +141,12 @@ describe("getComparisonInterval", () => {
110141
comparison,
111142
"UTC",
112143
);
144+
if (test.output === undefined) {
145+
expect(comparisonInterval).toBeUndefined();
146+
return;
147+
}
148+
149+
const { start: expectedStart, end: expectedEnd } = test.output;
113150
expect(comparisonInterval?.start.toJSDate()).toEqual(expectedStart);
114151
expect(comparisonInterval?.end.toJSDate()).toEqual(expectedEnd);
115152
});

web-common/src/lib/time/comparisons/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
TimeOffsetType,
1414
TimeRangePreset,
1515
} from "../types";
16+
import { isNewRillTimeFormat } from "@rilldata/web-common/features/dashboards/url-state/time-ranges/parser.ts";
1617

1718
export function getComparisonTransform(
1819
start: Date,
@@ -316,7 +317,8 @@ export function getComparisonInterval(
316317
comparisonRange: string | undefined,
317318
activeTimeZone: string,
318319
): Interval<true> | undefined {
319-
if (!interval || !comparisonRange) return undefined;
320+
if (!interval || !comparisonRange || isNewRillTimeFormat(comparisonRange))
321+
return undefined;
320322

321323
let comparisonInterval: Interval | undefined = undefined;
322324

@@ -348,7 +350,11 @@ export function getComparisonInterval(
348350
}
349351
} else {
350352
const normalizedRange = comparisonRange.replace(",", "/");
351-
comparisonInterval = Interval.fromISO(normalizedRange).mapEndpoints((dt) =>
353+
const normalizedInterval = Interval.fromISO(normalizedRange);
354+
// Safeguard against unknown comparison range format.
355+
if (!normalizedInterval.isValid) return undefined;
356+
357+
comparisonInterval = normalizedInterval.mapEndpoints((dt) =>
352358
dt.setZone(activeTimeZone),
353359
);
354360
}

0 commit comments

Comments
 (0)