diff --git a/packages/app/global-setup.js b/packages/app/global-setup.js new file mode 100644 index 00000000..e96f7d07 --- /dev/null +++ b/packages/app/global-setup.js @@ -0,0 +1,3 @@ +module.exports = async () => { + process.env.TZ = 'America/New_York'; +}; diff --git a/packages/app/jest.config.js b/packages/app/jest.config.js index 55ef0ca0..8b98c91d 100644 --- a/packages/app/jest.config.js +++ b/packages/app/jest.config.js @@ -2,7 +2,7 @@ module.exports = { preset: 'ts-jest/presets/js-with-ts', testEnvironment: '@deploysentinel/jest-rtl-debugger/environment', setupFilesAfterEnv: ['/setup-jest.ts'], - globalSetup: '@deploysentinel/jest-rtl-debugger/globalSetup', + globalSetup: '/global-setup.js', roots: ['/src'], transform: { '^.+\\.tsx?$': 'ts-jest', diff --git a/packages/app/src/DashboardPage.tsx b/packages/app/src/DashboardPage.tsx index 71800604..80b8cfd8 100644 --- a/packages/app/src/DashboardPage.tsx +++ b/packages/app/src/DashboardPage.tsx @@ -34,7 +34,7 @@ import TabBar from './TabBar'; import HDXHistogramChart from './HDXHistogramChart'; import api from './api'; import { LogTableWithSidePanel } from './LogTableWithSidePanel'; -import { parseTimeQuery, useTimeQuery } from './timeQuery'; +import { parseTimeQuery, useNewTimeQuery, useTimeQuery } from './timeQuery'; import { EditSearchChartForm, EditMarkdownChartForm, @@ -535,7 +535,7 @@ function DashboardFilter({ } // TODO: This is a hack to set the default time range -const defaultTimeRange = parseTimeQuery('Past 1h', false); +const defaultTimeRange = parseTimeQuery('Past 1h', false) as [Date, Date]; export default function DashboardPage() { const { data: dashboardsData, isLoading: isDashboardsLoading } = api.useDashboards(); @@ -622,19 +622,17 @@ export default function DashboardPage() { const [editedChart, setEditedChart] = useState(); - const { - searchedTimeRange, - displayedTimeInputValue, - setDisplayedTimeInputValue, - onSearch, - } = useTimeQuery({ - isUTC: false, - defaultValue: 'Past 1h', - defaultTimeRange: [ - defaultTimeRange?.[0]?.getTime() ?? -1, - defaultTimeRange?.[1]?.getTime() ?? -1, - ], - }); + const { searchedTimeRange, displayedTimeInputValue, onSearch } = + useNewTimeQuery({ + isUTC: false, + initialDisplayValue: 'Past 1h', + initialTimeRange: defaultTimeRange, + }); + + const [input, setInput] = useState(displayedTimeInputValue); + useEffect(() => { + setInput(displayedTimeInputValue); + }, [displayedTimeInputValue]); const onAddChart = () => { setEditedChart({ @@ -766,13 +764,13 @@ export default function DashboardPage() { className="d-flex align-items-center" onSubmit={e => { e.preventDefault(); - onSearch(displayedTimeInputValue); + onSearch(input); }} style={{ height: 33 }} > { onSearch(range); }} diff --git a/packages/app/src/__test__/timeQuery.test.tsx b/packages/app/src/__test__/timeQuery.test.tsx index 8ec5c2bf..d144daae 100644 --- a/packages/app/src/__test__/timeQuery.test.tsx +++ b/packages/app/src/__test__/timeQuery.test.tsx @@ -106,7 +106,18 @@ describe('useTimeQuery tests', () => { const timeQueryRef = React.createRef(); testRouter.replace('/search?tq=Last+4H'); - render( + const { rerender } = render( + + + , + ); + jest.runAllTimers(); + + rerender( { ); }); + it('browser navigation of from/to qparmas updates the searched time range', async () => { + const timeQueryRef = React.createRef(); + testRouter.setIsReady(false); + testRouter.replace('/search'); + + const result = render( + + + , + ); + jest.runAllTimers(); + + testRouter.setIsReady(true); + + result.rerender( + + + , + ); + + expect(timeQueryRef.current?.displayedTimeInputValue).toMatchInlineSnapshot( + `"Past 1h"`, + ); + expect(timeQueryRef.current?.searchedTimeRange).toMatchInlineSnapshot(` + Array [ + 2023-10-03T15:45:00.000Z, + 2023-10-03T16:00:00.000Z, + ] + `); + + // 10/03/23 from 04:00am EDT to 08:00am EDT + testRouter.replace('/search?from=1696320000000&to=1696334400000'); + + result.rerender( + + + , + ); + + result.rerender( + + + , + ); + + expect(timeQueryRef.current?.displayedTimeInputValue).toMatchInlineSnapshot( + `"Oct 3 04:00:00 - Oct 3 08:00:00"`, + ); + expect(timeQueryRef.current?.searchedTimeRange).toMatchInlineSnapshot(` + Array [ + 2023-10-03T08:00:00.000Z, + 2023-10-03T12:00:00.000Z, + ] + `); + }); + + it('overrides initial value with async updated `from` and `to` params', async () => { + const timeQueryRef = React.createRef(); + // 10/03/23 from 04:00am EDT to 08:00am EDT + testRouter.setIsReady(false); + testRouter.replace('/search'); + + const result = render( + + + , + ); + jest.runAllTimers(); + + testRouter.replace('/search?from=1696320000000&to=1696334400000'); + testRouter.setIsReady(true); + + result.rerender( + + + , + ); + + expect(timeQueryRef.current?.displayedTimeInputValue).toMatchInlineSnapshot( + `"Oct 3 04:00:00 - Oct 3 08:00:00"`, + ); + expect(timeQueryRef.current?.searchedTimeRange).toMatchInlineSnapshot(` + Array [ + 2023-10-03T08:00:00.000Z, + 2023-10-03T12:00:00.000Z, + ] + `); + }); + it('accepts `from` and `to` url params', async () => { const timeQueryRef = React.createRef(); // 10/03/23 from 04:00am EDT to 08:00am EDT @@ -178,7 +308,18 @@ describe('useTimeQuery tests', () => { '/search?from=1696320000000&to=1696334400000&tq=Past+1h', ); - render( + const result = render( + + + , + ); + jest.runAllTimers(); + + result.rerender( { const [start, end] = parseTimeQuery(timeQuery, isUTC); // TODO: Add validation UI if (start != null && end != null) { - setSearchedTimeRange([start, end]); setTimeRangeQuery({ from: start.getTime(), to: end.getTime() }); - const dateRangeStr = dateRangeToString([start, end], isUTC); - setDisplayedTimeInputValue(dateRangeStr); } }, - [isUTC, setTimeRangeQuery, setDisplayedTimeInputValue], + [isUTC, setTimeRangeQuery], ); useEffect(() => { - // On mount, we check if there is a `from` and `to` that we should use - // and if there isn't an inputTimeQuery - if ( - initialFrom.current && - initialTo.current && - !initialInputTimeQuery.current && - !initializedTimeRange.current - ) { - initializedTimeRange.current = true; - const start = new Date(initialFrom.current); - const end = new Date(initialTo.current); + if (from != null && to != null && inputTimeQuery == null && isReady) { + const start = new Date(from); + const end = new Date(to); if (isValid(start) && isValid(end)) { setSearchedTimeRange([start, end]); - setTimeRangeQuery({ from: start.getTime(), to: end.getTime() }); const dateRangeStr = dateRangeToString([start, end], isUTC); setDisplayedTimeInputValue(dateRangeStr); } + } else if ( + from == null && + to == null && + inputTimeQuery == null && + isReady + ) { + setSearchedTimeRange(initialTimeRange); + const dateRangeStr = dateRangeToString(initialTimeRange, isUTC); + setDisplayedTimeInputValue(initialDisplayValue ?? dateRangeStr); } - }, [isUTC, setTimeRangeQuery]); + }, [ + isReady, + inputTimeQuery, + isUTC, + from, + to, + initialDisplayValue, + initialTimeRange, + ]); useEffect(() => { // If there is a `tq` param passed in, use it to set the time range and