[Uptime] Feature/refactor context initialization (#54494)

* update refactor

* refactor context initilization

* rename values

* fix tests

Co-authored-by: Justin Kambic <justin.kambic@elastic.co>
This commit is contained in:
Shahzad 2020-01-15 04:51:17 +01:00 committed by Justin Kambic
parent bd9d67ccc0
commit 1ae2d00ab6
30 changed files with 1132 additions and 768 deletions

View file

@ -1,81 +1,192 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MonitorCharts component renders the component without errors 1`] = `
<EuiFlexGroup>
<EuiFlexItem>
<DurationChart
loading={false}
locationDurationLines={
Array [
<ContextProvider
value={
Object {
"history": Object {
"action": "POP",
"block": [Function],
"canGo": [Function],
"createHref": [Function],
"entries": Array [
Object {
"line": Array [
Object {
"x": 1548697620000,
"y": 743928.2027027027,
},
Object {
"x": 1548697920000,
"y": 766840.0133333333,
},
Object {
"x": 1548698220000,
"y": 786970.8266666667,
},
Object {
"x": 1548698520000,
"y": 781064.7808219178,
},
Object {
"x": 1548698820000,
"y": 741563.04,
},
Object {
"x": 1548699120000,
"y": 759354.6756756756,
},
Object {
"x": 1548699420000,
"y": 737533.3866666667,
},
Object {
"x": 1548699720000,
"y": 728669.0266666666,
},
Object {
"x": 1548700020000,
"y": 719951.64,
},
Object {
"x": 1548700320000,
"y": 769181.7866666666,
},
Object {
"x": 1548700620000,
"y": 740805.2666666667,
},
],
"name": "somewhere",
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
]
],
"go": [Function],
"goBack": [Function],
"goForward": [Function],
"index": 0,
"length": 1,
"listen": [Function],
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"push": [Function],
"replace": [Function],
},
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"match": Object {
"isExact": true,
"params": Object {},
"path": "/",
"url": "/",
},
"staticContext": undefined,
}
}
>
<MonitorChartsComponent
danger="dangerColor"
data={
Object {
"monitorChartsData": Object {
"durationMaxValue": 6669234,
"locationDurationLines": Array [
Object {
"line": Array [
Object {
"x": 1548697620000,
"y": 743928.2027027027,
},
Object {
"x": 1548697920000,
"y": 766840.0133333333,
},
Object {
"x": 1548698220000,
"y": 786970.8266666667,
},
Object {
"x": 1548698520000,
"y": 781064.7808219178,
},
Object {
"x": 1548698820000,
"y": 741563.04,
},
Object {
"x": 1548699120000,
"y": 759354.6756756756,
},
Object {
"x": 1548699420000,
"y": 737533.3866666667,
},
Object {
"x": 1548699720000,
"y": 728669.0266666666,
},
Object {
"x": 1548700020000,
"y": 719951.64,
},
Object {
"x": 1548700320000,
"y": 769181.7866666666,
},
Object {
"x": 1548700620000,
"y": 740805.2666666667,
},
],
"name": "somewhere",
},
],
"status": Array [
Object {
"down": null,
"total": 74,
"up": 74,
"x": 1548697620000,
},
Object {
"down": null,
"total": 75,
"up": 75,
"x": 1548697920000,
},
Object {
"down": null,
"total": 75,
"up": 75,
"x": 1548698220000,
},
Object {
"down": null,
"total": 73,
"up": 73,
"x": 1548698520000,
},
Object {
"down": null,
"total": 75,
"up": 75,
"x": 1548698820000,
},
Object {
"down": null,
"total": 74,
"up": 74,
"x": 1548699120000,
},
Object {
"down": null,
"total": 75,
"up": 75,
"x": 1548699420000,
},
Object {
"down": null,
"total": 75,
"up": 75,
"x": 1548699720000,
},
Object {
"down": null,
"total": 75,
"up": 75,
"x": 1548700020000,
},
Object {
"down": null,
"total": 75,
"up": 75,
"x": 1548700320000,
},
Object {
"down": null,
"total": 75,
"up": 75,
"x": 1548700620000,
},
],
"statusMaxCount": 75,
},
}
meanColor="mean"
rangeColor="range"
/>
</EuiFlexItem>
<EuiFlexItem>
<withApollo(Component)
absoluteEndDate={20}
absoluteStartDate={20}
height="400px"
isResponsive={false}
variables={
Object {
"dateRangeEnd": "2011-12-03T10:15:30+01:00",
"dateRangeStart": "2011-12-03T10:15:30+01:00",
"monitorId": "something",
}
}
/>
</EuiFlexItem>
</EuiFlexGroup>
}
dateRangeEnd="2011-12-03T10:15:30+01:00"
dateRangeStart="2011-12-03T10:15:30+01:00"
loading={false}
mean="mean"
monitorId="something"
range="range"
success="success"
/>
</ContextProvider>
`;

View file

@ -111,155 +111,57 @@ exports[`UptimeDatePicker component renders properly with mock data 1`] = `
</div>
`;
exports[`UptimeDatePicker component renders properly without commonlyUsedRanges prop 1`] = `
<div
class="euiFlexGroup euiFlexGroup--gutterSmall euiFlexGroup--directionRow euiSuperDatePicker__flexWrapper"
>
<div
class="euiFlexItem"
>
<div
class="euiFormControlLayout euiFormControlLayout--group euiSuperDatePicker"
>
<div
class="euiPopover euiPopover--anchorDownLeft"
id="QuickSelectPopover"
>
<div
class="euiPopover__anchor euiQuickSelectPopover__anchor"
>
<button
aria-label="Date quick select"
class="euiButtonEmpty euiButtonEmpty--primary euiButtonEmpty--xSmall euiButtonEmpty--iconRight euiFormControlLayout__prepend"
data-test-subj="superDatePickerToggleQuickMenuButton"
type="button"
>
<span
class="euiButtonEmpty__content"
>
<svg
aria-hidden="true"
class="euiIcon euiIcon--medium euiIcon-isLoading euiButtonEmpty__icon"
focusable="false"
height="16"
role="img"
viewBox="0 0 16 16"
width="16"
xmlns="http://www.w3.org/2000/svg"
/>
<span
class="euiButtonEmpty__text euiQuickSelectPopover__buttonText"
>
<svg
aria-hidden="true"
class="euiIcon euiIcon--medium euiIcon-isLoading"
focusable="false"
height="16"
role="img"
viewBox="0 0 16 16"
width="16"
xmlns="http://www.w3.org/2000/svg"
/>
</span>
</span>
</button>
</div>
</div>
<div
class="euiFormControlLayout__childrenWrapper"
>
<div
class="euiDatePickerRange euiDatePickerRange--inGroup"
>
<button
class="euiSuperDatePicker__prettyFormat"
data-test-subj="superDatePickerShowDatesButton"
>
Last 15 minutes
<span
class="euiSuperDatePicker__prettyFormatLink"
>
Show dates
</span>
</button>
</div>
</div>
</div>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero"
>
<span
class="euiToolTipAnchor"
>
<button
class="euiButton euiButton--primary euiSuperUpdateButton euiButton--fill"
data-test-subj="superDatePickerApplyTimeButton"
type="button"
>
<span
class="euiButton__content"
>
<svg
aria-hidden="true"
class="euiIcon euiIcon--medium euiIcon-isLoading euiButton__icon"
focusable="false"
height="16"
role="img"
viewBox="0 0 16 16"
width="16"
xmlns="http://www.w3.org/2000/svg"
/>
<span
class="euiButton__text euiSuperUpdateButton__text"
>
Refresh
</span>
</span>
</button>
</span>
</div>
</div>
`;
exports[`UptimeDatePicker component validates props with shallow render 1`] = `
<EuiSuperDatePicker
commonlyUsedRanges={
Array [
Object {
"end": "now",
"label": "Today",
"start": "now/d",
<ContextProvider
value={
Object {
"history": Object {
"action": "POP",
"block": [Function],
"canGo": [Function],
"createHref": [Function],
"entries": Array [
Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
],
"go": [Function],
"goBack": [Function],
"goForward": [Function],
"index": 0,
"length": 1,
"listen": [Function],
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"push": [Function],
"replace": [Function],
},
Object {
"end": "now",
"label": "Week to date",
"start": "now/w",
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
Object {
"end": "now",
"label": "Month to date",
"start": "now/M",
"match": Object {
"isExact": true,
"params": Object {},
"path": "/",
"url": "/",
},
Object {
"end": "now",
"label": "Year to date",
"start": "now/y",
},
]
"staticContext": undefined,
}
}
dateFormat="MMM D, YYYY @ HH:mm:ss.SSS"
end="now"
isAutoRefreshOnly={false}
isDisabled={false}
isPaused={false}
onRefresh={[MockFunction]}
onRefreshChange={[Function]}
onTimeChange={[Function]}
recentlyUsedRanges={Array []}
refreshInterval={60000}
showUpdateButton={true}
start="now-15m"
timeFormat="HH:mm"
/>
>
<UptimeDatePicker />
</ContextProvider>
`;

View file

@ -9,6 +9,7 @@ import DateMath from '@elastic/datemath';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { MonitorChartsComponent } from '../monitor_charts';
import { MonitorChart } from '../../../../common/graphql/types';
import { renderWithRouter } from '../../../lib';
describe('MonitorCharts component', () => {
let dateMathSpy: any;
@ -63,17 +64,19 @@ describe('MonitorCharts component', () => {
it('renders the component without errors', () => {
const component = shallowWithIntl(
<MonitorChartsComponent
danger="dangerColor"
data={{ monitorChartsData: chartResponse.monitorChartsData }}
loading={false}
mean="mean"
range="range"
success="success"
monitorId="something"
dateRangeStart="2011-12-03T10:15:30+01:00"
dateRangeEnd="2011-12-03T10:15:30+01:00"
/>
renderWithRouter(
<MonitorChartsComponent
danger="dangerColor"
data={{ monitorChartsData: chartResponse.monitorChartsData }}
loading={false}
mean="mean"
range="range"
success="success"
monitorId="something"
dateRangeStart="2011-12-03T10:15:30+01:00"
dateRangeEnd="2011-12-03T10:15:30+01:00"
/>
)
);
expect(component).toMatchSnapshot();
});

View file

@ -7,20 +7,16 @@
import { shallowWithIntl, renderWithIntl } from 'test_utils/enzyme_helpers';
import React from 'react';
import { UptimeDatePicker } from '../uptime_date_picker';
import { renderWithRouter } from '../../../lib';
describe('UptimeDatePicker component', () => {
it('validates props with shallow render', () => {
const component = shallowWithIntl(<UptimeDatePicker refreshApp={jest.fn()} />);
const component = shallowWithIntl(renderWithRouter(<UptimeDatePicker />));
expect(component).toMatchSnapshot();
});
it('renders properly with mock data', () => {
const component = renderWithIntl(<UptimeDatePicker refreshApp={jest.fn()} />);
expect(component).toMatchSnapshot();
});
it('renders properly without commonlyUsedRanges prop', () => {
const component = renderWithIntl(<UptimeDatePicker refreshApp={jest.fn()} />);
const component = renderWithIntl(renderWithRouter(<UptimeDatePicker />));
expect(component).toMatchSnapshot();
});
});

View file

@ -9,7 +9,7 @@ import React, { useContext, useEffect, useRef } from 'react';
import * as d3 from 'd3';
import { i18n } from '@kbn/i18n';
import { DonutChartLegend } from './donut_chart_legend';
import { UptimeSettingsContext } from '../../../contexts';
import { UptimeThemeContext } from '../../../contexts';
interface DonutChartProps {
down: number;
@ -23,7 +23,7 @@ export const DonutChart = ({ height, down, up, width }: DonutChartProps) => {
const {
colors: { danger, gray },
} = useContext(UptimeSettingsContext);
} = useContext(UptimeThemeContext);
let upCount = up;
if (up === 0 && down === 0) {

View file

@ -9,7 +9,7 @@ import { EuiSpacer } from '@elastic/eui';
import React, { useContext } from 'react';
import styled from 'styled-components';
import { DonutChartLegendRow } from './donut_chart_legend_row';
import { UptimeSettingsContext } from '../../../contexts';
import { UptimeThemeContext } from '../../../contexts';
const LegendContainer = styled.div`
max-width: 260px;
@ -28,7 +28,7 @@ interface Props {
export const DonutChartLegend = ({ down, up }: Props) => {
const {
colors: { gray, danger },
} = useContext(UptimeSettingsContext);
} = useContext(UptimeThemeContext);
return (
<LegendContainer>
<DonutChartLegendRow

View file

@ -14,7 +14,7 @@ import { getChartDateLabel } from '../../../lib/helper';
import { withUptimeGraphQL, UptimeGraphQLQueryProps } from '../../higher_order';
import { snapshotHistogramQuery } from '../../../queries/snapshot_histogram_query';
import { ChartWrapper } from './chart_wrapper';
import { UptimeSettingsContext } from '../../../contexts';
import { UptimeThemeContext } from '../../../contexts';
import { ResponsiveWrapperProps, withResponsiveWrapper } from '../../higher_order';
import { HistogramResult } from '../../../../common/domain_types';
@ -53,7 +53,7 @@ export const SnapshotHistogramComponent: React.FC<Props> = ({
}: Props) => {
const {
colors: { danger, gray },
} = useContext(UptimeSettingsContext);
} = useContext(UptimeThemeContext);
if (!data || !data.queryResult)
/**
* TODO: the Fragment, EuiTitle, and EuiPanel should be extracted to a dumb component

View file

@ -1,16 +1,61 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`FilterStatusButton renders without errors for valid props 1`] = `
<EuiFilterButton
color="text"
data-test-subj="foo"
grow={true}
hasActiveFilters={false}
iconSide="right"
onClick={[Function]}
type="button"
withNext={true}
<ContextProvider
value={
Object {
"history": Object {
"action": "POP",
"block": [Function],
"canGo": [Function],
"createHref": [Function],
"entries": Array [
Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
],
"go": [Function],
"goBack": [Function],
"goForward": [Function],
"index": 0,
"length": 1,
"listen": [Function],
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"push": [Function],
"replace": [Function],
},
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"match": Object {
"isExact": true,
"params": Object {},
"path": "/",
"url": "/",
},
"staticContext": undefined,
}
}
>
Up
</EuiFilterButton>
<FilterStatusButton
content="Up"
dataTestSubj="foo"
value="up"
withNext={true}
/>
</ContextProvider>
`;

View file

@ -7,6 +7,7 @@
import React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { FilterStatusButton, FilterStatusButtonProps } from '../filter_status_button';
import { renderWithRouter } from '../../../../lib/';
describe('FilterStatusButton', () => {
let props: FilterStatusButtonProps;
@ -20,7 +21,7 @@ describe('FilterStatusButton', () => {
});
it('renders without errors for valid props', () => {
const wrapper = shallowWithIntl(<FilterStatusButton {...props} />);
const wrapper = shallowWithIntl(renderWithRouter(<FilterStatusButton {...props} />));
expect(wrapper).toMatchSnapshot();
});
});

View file

@ -15,7 +15,7 @@ import { MAP_SAVED_OBJECT_TYPE } from '../../../../../../maps/common/constants';
import { MapEmbeddable } from './types';
import { getLayerList } from './map_config';
import { UptimeSettingsContext } from '../../../../contexts';
import { UptimeThemeContext } from '../../../../contexts';
export interface EmbeddedMapProps {
upPoints: LocationPoint[];
@ -46,7 +46,7 @@ const EmbeddedPanel = styled.div`
`;
export const EmbeddedMap = ({ upPoints, downPoints }: EmbeddedMapProps) => {
const { colors } = useContext(UptimeSettingsContext);
const { colors } = useContext(UptimeThemeContext);
const [embeddable, setEmbeddable] = useState<MapEmbeddable>();
const embeddableRoot: React.RefObject<HTMLDivElement> = useRef<HTMLDivElement>(null);
const factory = start.getEmbeddableFactory(MAP_SAVED_OBJECT_TYPE);

View file

@ -5,11 +5,11 @@
*/
import React, { useContext } from 'react';
import moment from 'moment';
import styled from 'styled-components';
import { EuiBadge, EuiText } from '@elastic/eui';
import moment from 'moment';
import { FormattedMessage } from '@kbn/i18n/react';
import { UptimeSettingsContext } from '../../../contexts';
import { UptimeThemeContext } from '../../../contexts';
import { MonitorLocation } from '../../../../common/runtime_types';
const TimeStampSpan = styled.span`
@ -48,7 +48,7 @@ interface StatusTag {
export const LocationStatusTags = ({ locations }: Props) => {
const {
colors: { gray, danger },
} = useContext(UptimeSettingsContext);
} = useContext(UptimeThemeContext);
const upLocations: StatusTag[] = [];
const downLocations: StatusTag[] = [];

View file

@ -1,189 +1,197 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MonitorListDrawer component renders a MonitorListDrawer when there are many checks 1`] = `
<styled.div>
<EuiFlexGroup>
<EuiFlexItem
grow={true}
>
<EuiText>
<EuiLink
href="https://expired.badssl.com"
target="_blank"
>
https://expired.badssl.com
<EuiIcon
color="subbdued"
size="s"
type="popout"
/>
</EuiLink>
</EuiText>
</EuiFlexItem>
<EuiFlexItem
grow={false}
>
<Connect(MonitorListActionsPopoverComponent)
summary={
<ContextProvider
value={
Object {
"history": Object {
"action": "POP",
"block": [Function],
"canGo": [Function],
"createHref": [Function],
"entries": Array [
Object {
"monitor_id": "foo",
"state": Object {
"checks": Array [
Object {
"monitor": Object {
"ip": "127.0.0.1",
"status": "up",
},
"timestamp": "121",
},
Object {
"monitor": Object {
"ip": "127.0.0.2",
"status": "down",
},
"timestamp": "123",
},
Object {
"monitor": Object {
"ip": "127.0.0.3",
"status": "up",
},
"timestamp": "125",
},
],
"summary": Object {
"down": 0,
"up": 1,
},
"timestamp": "123",
"url": Object {
"domain": "expired.badssl.com",
"full": "https://expired.badssl.com",
},
},
}
}
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer
size="m"
/>
<MonitorStatusList
checks={
Array [
Object {
"monitor": Object {
"ip": "127.0.0.1",
"status": "up",
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"timestamp": "121",
],
"go": [Function],
"goBack": [Function],
"goForward": [Function],
"index": 0,
"length": 1,
"listen": [Function],
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
Object {
"monitor": Object {
"ip": "127.0.0.2",
"status": "down",
},
"timestamp": "123",
},
Object {
"monitor": Object {
"ip": "127.0.0.3",
"status": "up",
},
"timestamp": "125",
},
]
"push": [Function],
"replace": [Function],
},
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"match": Object {
"isExact": true,
"params": Object {},
"path": "/",
"url": "/",
},
"staticContext": undefined,
}
/>
<MostRecentError
error={
}
>
<MonitorListDrawerComponent
loadMonitorDetails={[Function]}
monitorDetails={
Object {
"message": "Get https://expired.badssl.com: x509: certificate has expired or is not yet valid",
"type": "io",
"error": Object {
"message": "Get https://expired.badssl.com: x509: certificate has expired or is not yet valid",
"type": "io",
},
"monitorId": "bad-ssl",
}
}
summary={
Object {
"monitor_id": "foo",
"state": Object {
"checks": Array [
Object {
"monitor": Object {
"ip": "127.0.0.1",
"status": "up",
},
"timestamp": "121",
},
Object {
"monitor": Object {
"ip": "127.0.0.2",
"status": "down",
},
"timestamp": "123",
},
Object {
"monitor": Object {
"ip": "127.0.0.3",
"status": "up",
},
"timestamp": "125",
},
],
"summary": Object {
"down": 0,
"up": 1,
},
"timestamp": "123",
"url": Object {
"domain": "expired.badssl.com",
"full": "https://expired.badssl.com",
},
},
}
}
monitorId="foo"
/>
</styled.div>
</ContextProvider>
`;
exports[`MonitorListDrawer component renders a MonitorListDrawer when there is only one check 1`] = `
<styled.div>
<EuiFlexGroup>
<EuiFlexItem
grow={true}
>
<EuiText>
<EuiLink
href="https://expired.badssl.com"
target="_blank"
>
https://expired.badssl.com
<EuiIcon
color="subbdued"
size="s"
type="popout"
/>
</EuiLink>
</EuiText>
</EuiFlexItem>
<EuiFlexItem
grow={false}
>
<Connect(MonitorListActionsPopoverComponent)
summary={
<ContextProvider
value={
Object {
"history": Object {
"action": "POP",
"block": [Function],
"canGo": [Function],
"createHref": [Function],
"entries": Array [
Object {
"monitor_id": "foo",
"state": Object {
"checks": Array [
Object {
"monitor": Object {
"ip": "127.0.0.1",
"status": "up",
},
"timestamp": "121",
},
],
"summary": Object {
"down": 0,
"up": 1,
},
"timestamp": "123",
"url": Object {
"domain": "expired.badssl.com",
"full": "https://expired.badssl.com",
},
},
}
}
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer
size="m"
/>
<MonitorStatusList
checks={
Array [
Object {
"monitor": Object {
"ip": "127.0.0.1",
"status": "up",
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"timestamp": "121",
],
"go": [Function],
"goBack": [Function],
"goForward": [Function],
"index": 0,
"length": 1,
"listen": [Function],
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
]
"push": [Function],
"replace": [Function],
},
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"match": Object {
"isExact": true,
"params": Object {},
"path": "/",
"url": "/",
},
"staticContext": undefined,
}
/>
<MostRecentError
error={
}
>
<MonitorListDrawerComponent
loadMonitorDetails={[Function]}
monitorDetails={
Object {
"message": "Get https://expired.badssl.com: x509: certificate has expired or is not yet valid",
"type": "io",
"error": Object {
"message": "Get https://expired.badssl.com: x509: certificate has expired or is not yet valid",
"type": "io",
},
"monitorId": "bad-ssl",
}
}
summary={
Object {
"monitor_id": "foo",
"state": Object {
"checks": Array [
Object {
"monitor": Object {
"ip": "127.0.0.1",
"status": "up",
},
"timestamp": "121",
},
],
"summary": Object {
"down": 0,
"up": 1,
},
"timestamp": "123",
"url": Object {
"domain": "expired.badssl.com",
"full": "https://expired.badssl.com",
},
},
}
}
monitorId="foo"
/>
</styled.div>
</ContextProvider>
`;

View file

@ -9,6 +9,7 @@ import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import React from 'react';
import { MonitorListDrawerComponent } from '../monitor_list_drawer';
import { MonitorDetails } from '../../../../../../common/runtime_types';
import { renderWithRouter } from '../../../../../lib';
describe('MonitorListDrawer component', () => {
let summary: MonitorSummary;
@ -52,11 +53,13 @@ describe('MonitorListDrawer component', () => {
it('renders nothing when no summary data is present', () => {
const component = shallowWithIntl(
<MonitorListDrawerComponent
loadMonitorDetails={loadMonitorDetails}
summary={summary}
monitorDetails={monitorDetails}
/>
renderWithRouter(
<MonitorListDrawerComponent
loadMonitorDetails={loadMonitorDetails}
summary={summary}
monitorDetails={monitorDetails}
/>
)
);
expect(component).toEqual({});
});
@ -64,22 +67,26 @@ describe('MonitorListDrawer component', () => {
it('renders nothing when no check data is present', () => {
delete summary.state.checks;
const component = shallowWithIntl(
<MonitorListDrawerComponent
summary={summary}
loadMonitorDetails={loadMonitorDetails}
monitorDetails={monitorDetails}
/>
renderWithRouter(
<MonitorListDrawerComponent
summary={summary}
loadMonitorDetails={loadMonitorDetails}
monitorDetails={monitorDetails}
/>
)
);
expect(component).toEqual({});
});
it('renders a MonitorListDrawer when there is only one check', () => {
const component = shallowWithIntl(
<MonitorListDrawerComponent
summary={summary}
loadMonitorDetails={loadMonitorDetails}
monitorDetails={monitorDetails}
/>
renderWithRouter(
<MonitorListDrawerComponent
summary={summary}
loadMonitorDetails={loadMonitorDetails}
monitorDetails={monitorDetails}
/>
)
);
expect(component).toMatchSnapshot();
});
@ -110,11 +117,13 @@ describe('MonitorListDrawer component', () => {
];
summary.state.checks = checks;
const component = shallowWithIntl(
<MonitorListDrawerComponent
summary={summary}
loadMonitorDetails={loadMonitorDetails}
monitorDetails={monitorDetails}
/>
renderWithRouter(
<MonitorListDrawerComponent
summary={summary}
loadMonitorDetails={loadMonitorDetails}
monitorDetails={monitorDetails}
/>
)
);
expect(component).toMatchSnapshot();
});

View file

@ -7,7 +7,7 @@
import React, { useContext } from 'react';
import { EuiHealth, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { UptimeSettingsContext } from '../../../../contexts';
import { UptimeThemeContext } from '../../../../contexts';
import { UP } from './monitor_status_list';
import { UNNAMED_LOCATION } from '../../../../../common/constants';
@ -25,7 +25,7 @@ interface MonitorStatusRowProps {
export const MonitorStatusRow = ({ locationNames, status }: MonitorStatusRowProps) => {
const {
colors: { success, danger },
} = useContext(UptimeSettingsContext);
} = useContext(UptimeThemeContext);
const color = status === UP ? success : danger;

View file

@ -8,7 +8,7 @@ import { EuiSuperDatePicker } from '@elastic/eui';
import React, { useContext } from 'react';
import { useUrlParams } from '../../hooks';
import { CLIENT_DEFAULTS } from '../../../common/constants';
import { UptimeSettingsContext } from '../../contexts';
import { UptimeRefreshContext, UptimeSettingsContext } from '../../contexts';
// TODO: when EUI exports types for this, this should be replaced
interface SuperDateRangePickerRangeChangedEvent {
@ -27,14 +27,11 @@ export interface CommonlyUsedRange {
display: string;
}
interface UptimeDatePickerProps {
refreshApp: () => void;
}
export const UptimeDatePicker = ({ refreshApp }: UptimeDatePickerProps) => {
export const UptimeDatePicker = () => {
const [getUrlParams, updateUrl] = useUrlParams();
const { autorefreshInterval, autorefreshIsPaused, dateRangeStart, dateRangeEnd } = getUrlParams();
const { commonlyUsedRanges } = useContext(UptimeSettingsContext);
const { refreshApp } = useContext(UptimeRefreshContext);
const euiCommonlyUsedRanges = commonlyUsedRanges
? commonlyUsedRanges.map(

View file

@ -4,5 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { UptimeRefreshContext } from './uptime_refresh_context';
export { UMSettingsContextValues, UptimeSettingsContext } from './uptime_settings_context';
export { UptimeRefreshContext, UptimeRefreshContextProvider } from './uptime_refresh_context';
export {
UptimeSettingsContextValues,
UptimeSettingsContext,
UptimeSettingsContextProvider,
} from './uptime_settings_context';
export { UptimeThemeContextProvider, UptimeThemeContext } from './uptime_theme_context';

View file

@ -1,27 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { createContext } from 'react';
import { History } from 'history';
interface Location {
pathname: string;
search: string;
}
interface UMRefreshContext {
lastRefresh: number;
history: History | undefined;
location: Location | undefined;
}
const defaultContext: UMRefreshContext = {
lastRefresh: 0,
history: undefined,
location: undefined,
};
export const UptimeRefreshContext = createContext(defaultContext);

View file

@ -0,0 +1,39 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { createContext, useMemo, useState } from 'react';
import { store } from '../state';
import { triggerAppRefresh } from '../state/actions';
interface UptimeRefreshContext {
lastRefresh: number;
refreshApp: () => void;
}
const defaultContext: UptimeRefreshContext = {
lastRefresh: 0,
refreshApp: () => {
throw new Error('App refresh was not initialized, set it when you invoke the context');
},
};
export const UptimeRefreshContext = createContext(defaultContext);
export const UptimeRefreshContextProvider: React.FC = ({ children }) => {
const [lastRefresh, setLastRefresh] = useState<number>(Date.now());
const refreshApp = () => {
const refreshTime = Date.now();
setLastRefresh(refreshTime);
store.dispatch(triggerAppRefresh(refreshTime));
};
const value = useMemo(() => {
return { lastRefresh, refreshApp };
}, [lastRefresh]);
return <UptimeRefreshContext.Provider value={value} children={children} />;
};

View file

@ -1,70 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import DateMath from '@elastic/datemath';
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
import { createContext } from 'react';
import { UptimeAppColors } from '../uptime_app';
import { CONTEXT_DEFAULTS } from '../../common/constants';
import { CommonlyUsedRange } from '../components/functional/uptime_date_picker';
export interface UMSettingsContextValues {
absoluteStartDate: number;
absoluteEndDate: number;
autorefreshIsPaused: boolean;
autorefreshInterval: number;
basePath: string;
colors: UptimeAppColors;
dateRangeStart: string;
dateRangeEnd: string;
isApmAvailable: boolean;
isInfraAvailable: boolean;
isLogsAvailable: boolean;
refreshApp: () => void;
commonlyUsedRanges?: CommonlyUsedRange[];
}
const {
AUTOREFRESH_IS_PAUSED,
AUTOREFRESH_INTERVAL,
BASE_PATH,
DATE_RANGE_START,
DATE_RANGE_END,
} = CONTEXT_DEFAULTS;
const parsedStart = DateMath.parse(DATE_RANGE_START);
const parsedEnd = DateMath.parse(DATE_RANGE_END);
const DEFAULT_ABSOLUTE_START_DATE = parsedStart ? parsedStart.valueOf() : 0;
const DEFAULT_ABSOLUTE_END_DATE = parsedEnd ? parsedEnd.valueOf() : 1;
/**
* These are default values for the context. These defaults are typically
* overwritten by the Uptime App upon its invocation.
*/
const defaultContext: UMSettingsContextValues = {
absoluteStartDate: DEFAULT_ABSOLUTE_START_DATE,
absoluteEndDate: DEFAULT_ABSOLUTE_END_DATE,
autorefreshIsPaused: AUTOREFRESH_IS_PAUSED,
autorefreshInterval: AUTOREFRESH_INTERVAL,
basePath: BASE_PATH,
colors: {
danger: euiLightVars.euiColorDanger,
mean: euiLightVars.euiColorPrimary,
range: euiLightVars.euiFocusBackgroundColor,
success: euiLightVars.euiColorSuccess,
warning: euiLightVars.euiColorWarning,
gray: euiLightVars.euiColorLightShade,
},
dateRangeStart: DATE_RANGE_START,
dateRangeEnd: DATE_RANGE_END,
isApmAvailable: true,
isInfraAvailable: true,
isLogsAvailable: true,
refreshApp: () => {
throw new Error('App refresh was not initialized, set it when you invoke the context');
},
};
export const UptimeSettingsContext = createContext(defaultContext);

View file

@ -0,0 +1,56 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { createContext, useMemo } from 'react';
import { useParams } from 'react-router-dom';
import { UptimeAppProps } from '../uptime_app';
import { CONTEXT_DEFAULTS } from '../../common/constants';
import { CommonlyUsedRange } from '../components/functional/uptime_date_picker';
export interface UptimeSettingsContextValues {
basePath: string;
dateRangeStart: string;
dateRangeEnd: string;
isApmAvailable: boolean;
isInfraAvailable: boolean;
isLogsAvailable: boolean;
commonlyUsedRanges?: CommonlyUsedRange[];
}
const { BASE_PATH, DATE_RANGE_START, DATE_RANGE_END } = CONTEXT_DEFAULTS;
/**
* These are default values for the context. These defaults are typically
* overwritten by the Uptime App upon its invocation.
*/
const defaultContext: UptimeSettingsContextValues = {
basePath: BASE_PATH,
dateRangeStart: DATE_RANGE_START,
dateRangeEnd: DATE_RANGE_END,
isApmAvailable: true,
isInfraAvailable: true,
isLogsAvailable: true,
};
export const UptimeSettingsContext = createContext(defaultContext);
export const UptimeSettingsContextProvider: React.FC<UptimeAppProps> = ({ children, ...props }) => {
const { basePath, isApmAvailable, isInfraAvailable, isLogsAvailable } = props;
const { dateRangeStart, dateRangeEnd } = useParams();
const value = useMemo(() => {
return {
basePath,
isApmAvailable,
isInfraAvailable,
isLogsAvailable,
dateRangeStart: dateRangeStart ?? DATE_RANGE_START,
dateRangeEnd: dateRangeEnd ?? DATE_RANGE_END,
};
}, [basePath, isApmAvailable, isInfraAvailable, isLogsAvailable, dateRangeStart, dateRangeEnd]);
return <UptimeSettingsContext.Provider value={value} children={children} />;
};

View file

@ -0,0 +1,65 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
import React, { createContext, useMemo } from 'react';
import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
import { UptimeAppColors } from '../uptime_app';
export interface UptimeThemeContextValues {
colors: UptimeAppColors;
}
/**
* These are default values for the context. These defaults are typically
* overwritten by the Uptime App upon its invocation.
*/
const defaultContext: UptimeThemeContextValues = {
colors: {
danger: euiLightVars.euiColorDanger,
mean: euiLightVars.euiColorPrimary,
range: euiLightVars.euiFocusBackgroundColor,
success: euiLightVars.euiColorSuccess,
warning: euiLightVars.euiColorWarning,
gray: euiLightVars.euiColorLightShade,
},
};
export const UptimeThemeContext = createContext(defaultContext);
interface ThemeContextProps {
darkMode: boolean;
}
export const UptimeThemeContextProvider: React.FC<ThemeContextProps> = ({ darkMode, children }) => {
let colors: UptimeAppColors;
if (darkMode) {
colors = {
danger: euiDarkVars.euiColorDanger,
mean: euiDarkVars.euiColorPrimary,
gray: euiDarkVars.euiColorLightShade,
range: euiDarkVars.euiFocusBackgroundColor,
success: euiDarkVars.euiColorSuccess,
warning: euiDarkVars.euiColorWarning,
};
} else {
colors = {
danger: euiLightVars.euiColorDanger,
mean: euiLightVars.euiColorPrimary,
gray: euiLightVars.euiColorLightShade,
range: euiLightVars.euiFocusBackgroundColor,
success: euiLightVars.euiColorSuccess,
warning: euiLightVars.euiColorWarning,
};
}
const value = useMemo(() => {
return {
colors,
};
}, [colors]);
return <UptimeThemeContext.Provider value={value} children={children} />;
};

View file

@ -1,50 +1,324 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`useUrlParams deletes keys that do not have truthy values 1`] = `
<UseUrlParamsTestComponent
hook={[Function]}
updateParams={
<Router
history={
Object {
"pagination": "",
"action": "POP",
"block": [Function],
"canGo": [Function],
"createHref": [Function],
"entries": Array [
Object {
"hash": "",
"key": "test",
"pathname": "/",
"search": "?g=%22%22&dateRangeStart=now-12&dateRangeEnd=now&pagination=foo",
"state": undefined,
},
],
"go": [Function],
"goBack": [Function],
"goForward": [Function],
"index": 0,
"length": 1,
"listen": [Function],
"location": Object {
"hash": "",
"key": "test",
"pathname": "/",
"search": "?g=%22%22&dateRangeStart=now-12&dateRangeEnd=now&pagination=foo",
"state": undefined,
},
"push": [MockFunction],
"replace": [Function],
}
}
intl={
Object {
"defaultFormats": Object {},
"defaultLocale": "en",
"formatDate": [Function],
"formatHTMLMessage": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatPlural": [Function],
"formatRelative": [Function],
"formatTime": [Function],
"formats": Object {
"date": Object {
"full": Object {
"day": "numeric",
"month": "long",
"weekday": "long",
"year": "numeric",
},
"long": Object {
"day": "numeric",
"month": "long",
"year": "numeric",
},
"medium": Object {
"day": "numeric",
"month": "short",
"year": "numeric",
},
"short": Object {
"day": "numeric",
"month": "numeric",
"year": "2-digit",
},
},
"number": Object {
"currency": Object {
"style": "currency",
},
"percent": Object {
"style": "percent",
},
},
"relative": Object {
"days": Object {
"units": "day",
},
"hours": Object {
"units": "hour",
},
"minutes": Object {
"units": "minute",
},
"months": Object {
"units": "month",
},
"seconds": Object {
"units": "second",
},
"years": Object {
"units": "year",
},
},
"time": Object {
"full": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"long": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"medium": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
},
"short": Object {
"hour": "numeric",
"minute": "numeric",
},
},
},
"formatters": Object {
"getDateTimeFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralFormat": [Function],
"getRelativeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"now": [Function],
"onError": [Function],
"textComponent": Symbol(react.fragment),
"timeZone": null,
}
}
>
<div>
{"absoluteDateRangeStart":20,"absoluteDateRangeEnd":20,"autorefreshInterval":60000,"autorefreshIsPaused":false,"dateRangeStart":"now-12","dateRangeEnd":"now","filters":"","search":"","selectedPingStatus":"","statusFilter":"","pagination":"foo"}
</div>
<button
id="setUrlParams"
onClick={[Function]}
<UseUrlParamsTestComponent
hook={[Function]}
updateParams={
Object {
"pagination": "",
}
}
>
Set url params
</button>
<button
id="getUrlParams"
onClick={[Function]}
>
Get url params
</button>
</UseUrlParamsTestComponent>
<div>
{"absoluteDateRangeStart":20,"absoluteDateRangeEnd":20,"autorefreshInterval":60000,"autorefreshIsPaused":false,"dateRangeStart":"now-12","dateRangeEnd":"now","filters":"","search":"","selectedPingStatus":"","statusFilter":"","pagination":"foo"}
</div>
<button
id="setUrlParams"
onClick={[Function]}
>
Set url params
</button>
<button
id="getUrlParams"
onClick={[Function]}
>
Get url params
</button>
</UseUrlParamsTestComponent>
</Router>
`;
exports[`useUrlParams gets the expected values using the context 1`] = `
<UseUrlParamsTestComponent
hook={[Function]}
<Router
history={
Object {
"action": "POP",
"block": [Function],
"canGo": [Function],
"createHref": [Function],
"entries": Array [
Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
],
"go": [Function],
"goBack": [Function],
"goForward": [Function],
"index": 0,
"length": 1,
"listen": [Function],
"location": Object {
"hash": "",
"key": "TestKeyForTesting",
"pathname": "/",
"search": "",
"state": undefined,
},
"push": [Function],
"replace": [Function],
}
}
intl={
Object {
"defaultFormats": Object {},
"defaultLocale": "en",
"formatDate": [Function],
"formatHTMLMessage": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatPlural": [Function],
"formatRelative": [Function],
"formatTime": [Function],
"formats": Object {
"date": Object {
"full": Object {
"day": "numeric",
"month": "long",
"weekday": "long",
"year": "numeric",
},
"long": Object {
"day": "numeric",
"month": "long",
"year": "numeric",
},
"medium": Object {
"day": "numeric",
"month": "short",
"year": "numeric",
},
"short": Object {
"day": "numeric",
"month": "numeric",
"year": "2-digit",
},
},
"number": Object {
"currency": Object {
"style": "currency",
},
"percent": Object {
"style": "percent",
},
},
"relative": Object {
"days": Object {
"units": "day",
},
"hours": Object {
"units": "hour",
},
"minutes": Object {
"units": "minute",
},
"months": Object {
"units": "month",
},
"seconds": Object {
"units": "second",
},
"years": Object {
"units": "year",
},
},
"time": Object {
"full": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"long": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"medium": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
},
"short": Object {
"hour": "numeric",
"minute": "numeric",
},
},
},
"formatters": Object {
"getDateTimeFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralFormat": [Function],
"getRelativeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"now": [Function],
"onError": [Function],
"textComponent": Symbol(react.fragment),
"timeZone": null,
}
}
>
<div>
{"absoluteDateRangeStart":20,"absoluteDateRangeEnd":20,"autorefreshInterval":60000,"autorefreshIsPaused":false,"dateRangeStart":"now-19d","dateRangeEnd":"now-1m","filters":"","search":"","selectedPingStatus":"","statusFilter":""}
</div>
<button
id="setUrlParams"
onClick={[Function]}
<UseUrlParamsTestComponent
hook={[Function]}
>
Set url params
</button>
<button
id="getUrlParams"
onClick={[Function]}
>
Get url params
</button>
</UseUrlParamsTestComponent>
<div>
{"absoluteDateRangeStart":20,"absoluteDateRangeEnd":20,"autorefreshInterval":60000,"autorefreshIsPaused":false,"dateRangeStart":"now-15m","dateRangeEnd":"now","filters":"","search":"","selectedPingStatus":"","statusFilter":""}
</div>
<button
id="setUrlParams"
onClick={[Function]}
>
Set url params
</button>
<button
id="getUrlParams"
onClick={[Function]}
>
Get url params
</button>
</UseUrlParamsTestComponent>
</Router>
`;

View file

@ -8,16 +8,15 @@ import { mountWithIntl } from 'test_utils/enzyme_helpers';
import DateMath from '@elastic/datemath';
import React, { useState, Fragment } from 'react';
import { useUrlParams, UptimeUrlParamsHook } from '../use_url_params';
import { RouteComponentProps } from 'react-router-dom';
import { UptimeRefreshContext } from '../../contexts';
import { renderWithRouter } from '../../lib';
import { createMemoryHistory } from 'history';
interface MockUrlParamsComponentProps {
hook: UptimeUrlParamsHook;
updateParams?: { [key: string]: any };
}
let mockRouter: RouteComponentProps;
const UseUrlParamsTestComponent = ({ hook, updateParams }: MockUrlParamsComponentProps) => {
const [params, setParams] = useState({});
const [getUrlParams, updateUrlParams] = hook();
@ -42,61 +41,45 @@ const UseUrlParamsTestComponent = ({ hook, updateParams }: MockUrlParamsComponen
describe('useUrlParams', () => {
let dateMathSpy: any;
const MOCK_DATE_VALUE = 20;
beforeEach(() => {
mockRouter = {
// @ts-ignore other properties aren't needed for this test
history: {
push: jest.fn(),
},
location: {
pathname: '',
search: '?g=""',
state: {},
hash: '',
},
match: {
params: '',
isExact: true,
path: '/',
url: 'http://elastic.co',
},
};
dateMathSpy = jest.spyOn(DateMath, 'parse');
dateMathSpy.mockReturnValue(MOCK_DATE_VALUE);
});
it('accepts router props, updates URL params, and returns the current params', () => {
const history = createMemoryHistory();
jest.spyOn(history, 'push');
const component = mountWithIntl(
<UptimeRefreshContext.Provider
value={{ lastRefresh: 123, history: mockRouter.history, location: mockRouter.location }}
>
<UseUrlParamsTestComponent hook={useUrlParams} />
</UptimeRefreshContext.Provider>
renderWithRouter(
<UptimeRefreshContext.Provider value={{ lastRefresh: 123, refreshApp: jest.fn() }}>
<UseUrlParamsTestComponent hook={useUrlParams} />
</UptimeRefreshContext.Provider>,
history
)
);
const setUrlParamsButton = component.find('#setUrlParams');
setUrlParamsButton.simulate('click');
expect(mockRouter.history.push).toHaveBeenCalledWith({
pathname: '',
search: 'g=%22%22&dateRangeStart=now-12d&dateRangeEnd=now',
expect(history.push).toHaveBeenCalledWith({
pathname: '/',
search: 'dateRangeStart=now-12d&dateRangeEnd=now',
});
});
it('gets the expected values using the context', () => {
const component = mountWithIntl(
<UptimeRefreshContext.Provider
value={{
lastRefresh: 123,
history: mockRouter.history,
location: {
...mockRouter.location,
search: 'g=%22%22&dateRangeStart=now-19d&dateRangeEnd=now-1m',
},
}}
>
<UseUrlParamsTestComponent hook={useUrlParams} />
</UptimeRefreshContext.Provider>
renderWithRouter(
<UptimeRefreshContext.Provider
value={{
lastRefresh: 123,
refreshApp: jest.fn(),
}}
>
<UseUrlParamsTestComponent hook={useUrlParams} />
</UptimeRefreshContext.Provider>
)
);
const getUrlParamsButton = component.find('#getUrlParams');
@ -106,17 +89,24 @@ describe('useUrlParams', () => {
});
it('deletes keys that do not have truthy values', () => {
mockRouter.location.search = 'g=%22%22&dateRangeStart=now-12&dateRangeEnd=now&pagination=foo';
const history = createMemoryHistory({
initialEntries: ['/?g=%22%22&dateRangeStart=now-12&dateRangeEnd=now&pagination=foo'],
});
history.location.key = 'test';
jest.spyOn(history, 'push');
const component = mountWithIntl(
<UptimeRefreshContext.Provider
value={{
lastRefresh: 123,
history: mockRouter.history,
location: mockRouter.location,
}}
>
<UseUrlParamsTestComponent hook={useUrlParams} updateParams={{ pagination: '' }} />
</UptimeRefreshContext.Provider>
renderWithRouter(
<UptimeRefreshContext.Provider
value={{
lastRefresh: 123,
refreshApp: jest.fn(),
}}
>
<UseUrlParamsTestComponent hook={useUrlParams} updateParams={{ pagination: '' }} />
</UptimeRefreshContext.Provider>,
history
)
);
const getUrlParamsButton = component.find('#getUrlParams');
@ -126,11 +116,11 @@ describe('useUrlParams', () => {
expect(component).toMatchSnapshot();
const setUrlParmsButton = component.find('#setUrlParams');
setUrlParmsButton.simulate('click');
const setUrlParamsButton = component.find('#setUrlParams');
setUrlParamsButton.simulate('click');
expect(mockRouter.history.push).toHaveBeenCalledWith({
pathname: '',
expect(history.push).toHaveBeenCalledWith({
pathname: '/',
search: 'g=%22%22&dateRangeStart=now-12&dateRangeEnd=now',
});
});

View file

@ -5,8 +5,7 @@
*/
import qs from 'querystring';
import { useContext } from 'react';
import { UptimeRefreshContext } from '../contexts';
import { useLocation, useHistory } from 'react-router-dom';
import { UptimeUrlParams, getSupportedUrlParams } from '../lib/helper';
type GetUrlParams = () => UptimeUrlParams;
@ -15,12 +14,13 @@ type UpdateUrlParams = (updatedParams: { [key: string]: string | number | boolea
export type UptimeUrlParamsHook = () => [GetUrlParams, UpdateUrlParams];
export const useUrlParams: UptimeUrlParamsHook = () => {
const refreshContext = useContext(UptimeRefreshContext);
const location = useLocation();
const history = useHistory();
const getUrlParams: GetUrlParams = () => {
let search: string | undefined;
if (refreshContext.location) {
search = refreshContext.location.search;
if (location) {
search = location.search;
}
const params = search ? { ...qs.parse(search[0] === '?' ? search.slice(1) : search) } : {};
@ -28,11 +28,8 @@ export const useUrlParams: UptimeUrlParamsHook = () => {
};
const updateUrlParams: UpdateUrlParams = updatedParams => {
if (!refreshContext.history || !refreshContext.location) return;
const {
history,
location: { pathname, search },
} = refreshContext;
if (!history || !location) return;
const { pathname, search } = location;
const currentParams: any = qs.parse(search[0] === '?' ? search.slice(1) : search);
const mergedParams = {
...currentParams,

View file

@ -0,0 +1,21 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import { Router } from 'react-router-dom';
import { MemoryHistory } from 'history/createMemoryHistory';
import { createMemoryHistory } from 'history';
export const renderWithRouter = (Component: any, customHistory?: MemoryHistory) => {
if (customHistory) {
return <Router history={customHistory}>{Component}</Router>;
}
const history = createMemoryHistory();
history.location.key = 'TestKeyForTesting';
return <Router history={history}>{Component}</Router>;
};

View file

@ -0,0 +1,7 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export { renderWithRouter } from './helper/render_with_router';

View file

@ -9,7 +9,7 @@ import React, { Fragment, useContext, useState } from 'react';
import { useParams } from 'react-router-dom';
import { MonitorCharts, PingList } from '../components/functional';
import { UMUpdateBreadcrumbs } from '../lib/lib';
import { UptimeSettingsContext } from '../contexts';
import { UptimeRefreshContext, UptimeThemeContext } from '../contexts';
import { useUptimeTelemetry, useUrlParams, UptimePage } from '../hooks';
import { useTrackPageview } from '../../../infra/public';
import { MonitorStatusDetails } from '../components/functional/monitor_status_details';
@ -25,7 +25,8 @@ export const MonitorPage = ({ setBreadcrumbs }: MonitorPageProps) => {
monitorId = atob(monitorId || '');
const [pingListPageCount, setPingListPageCount] = useState<number>(10);
const { colors, refreshApp } = useContext(UptimeSettingsContext);
const { colors } = useContext(UptimeThemeContext);
const { refreshApp } = useContext(UptimeRefreshContext);
const [getUrlParams, updateUrlParams] = useUrlParams();
const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = getUrlParams();
const { dateRangeStart, dateRangeEnd, selectedPingStatus } = params;

View file

@ -16,7 +16,6 @@ import {
StatusPanel,
} from '../components/functional';
import { UMUpdateBreadcrumbs } from '../lib/lib';
import { UptimeSettingsContext } from '../contexts';
import { useIndexPattern, useUrlParams, useUptimeTelemetry, UptimePage } from '../hooks';
import { stringifyUrlParams } from '../lib/helper/stringify_url_params';
import { useTrackPageview } from '../../../infra/public';
@ -25,6 +24,7 @@ import { AutocompleteProviderRegister, esKuery } from '../../../../../../src/plu
import { store } from '../state';
import { setEsKueryString } from '../state/actions';
import { PageHeader } from './page_header';
import { UptimeThemeContext } from '../contexts/uptime_theme_context';
interface OverviewPageProps {
autocomplete: Pick<AutocompleteProviderRegister, 'getProvider'>;
@ -48,7 +48,7 @@ const EuiFlexItemStyled = styled(EuiFlexItem)`
`;
export const OverviewPage = ({ autocomplete, setBreadcrumbs }: Props) => {
const { colors } = useContext(UptimeSettingsContext);
const { colors } = useContext(UptimeThemeContext);
const [getUrlParams, updateUrl] = useUrlParams();
const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = getUrlParams();
const {

View file

@ -5,7 +5,7 @@
*/
import { EuiTitle, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import React, { useEffect, useState, useContext } from 'react';
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { useRouteMatch, useParams } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
@ -14,7 +14,6 @@ import { AppState } from '../state';
import { selectSelectedMonitor } from '../state/selectors';
import { getMonitorPageBreadcrumb, getOverviewPageBreadcrumbs } from '../breadcrumbs';
import { stringifyUrlParams } from '../lib/helper/stringify_url_params';
import { UptimeSettingsContext } from '../contexts';
import { getTitle } from '../lib/helper/get_title';
import { UMUpdateBreadcrumbs } from '../lib/lib';
import { MONITOR_ROUTE } from '../routes';
@ -28,7 +27,6 @@ export const PageHeaderComponent = ({ monitorStatus, setBreadcrumbs }: PageHeade
const monitorPage = useRouteMatch({
path: MONITOR_ROUTE,
});
const { refreshApp } = useContext(UptimeSettingsContext);
const { absoluteDateRangeStart, absoluteDateRangeEnd, ...params } = useParams();
@ -61,6 +59,10 @@ export const PageHeaderComponent = ({ monitorStatus, setBreadcrumbs }: PageHeade
}
}, [headerText, setBreadcrumbs, params, monitorPage]);
useEffect(() => {
document.title = getTitle();
}, []);
return (
<>
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween" gutterSize="s">
@ -70,7 +72,7 @@ export const PageHeaderComponent = ({ monitorStatus, setBreadcrumbs }: PageHeade
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<UptimeDatePicker refreshApp={refreshApp} />
<UptimeDatePicker />
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="s" />

View file

@ -4,25 +4,24 @@
* you may not use this file except in compliance with the Elastic License.
*/
import DateMath from '@elastic/datemath';
import { EuiPage } from '@elastic/eui';
import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
import { EuiPage, EuiErrorBoundary } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useEffect, useState } from 'react';
import React, { useEffect } from 'react';
import { ApolloProvider } from 'react-apollo';
import { Provider as ReduxProvider } from 'react-redux';
import { BrowserRouter as Router, Route, RouteComponentProps } from 'react-router-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { I18nStart, ChromeBreadcrumb, LegacyCoreStart } from 'src/core/public';
import { PluginsStart } from 'ui/new_platform/new_platform';
import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
import { UMGraphQLClient, UMUpdateBreadcrumbs, UMUpdateBadge } from './lib/lib';
import { UptimeRefreshContext, UptimeSettingsContext, UMSettingsContextValues } from './contexts';
import {
UptimeRefreshContextProvider,
UptimeSettingsContextProvider,
UptimeThemeContextProvider,
} from './contexts';
import { CommonlyUsedRange } from './components/functional/uptime_date_picker';
import { useUrlParams } from './hooks';
import { getTitle } from './lib/helper/get_title';
import { store } from './state';
import { setBasePath, triggerAppRefresh } from './state/actions';
import { setBasePath } from './state/actions';
import { PageRouter } from './routes';
export interface UptimeAppColors {
@ -60,11 +59,7 @@ const Application = (props: UptimeAppProps) => {
client,
core,
darkMode,
commonlyUsedRanges,
i18n: i18nCore,
isApmAvailable,
isInfraAvailable,
isLogsAvailable,
plugins,
renderGlobalHelpControls,
routerBasename,
@ -72,28 +67,6 @@ const Application = (props: UptimeAppProps) => {
setBadge,
} = props;
let colors: UptimeAppColors;
if (darkMode) {
colors = {
danger: euiDarkVars.euiColorDanger,
mean: euiDarkVars.euiColorPrimary,
gray: euiDarkVars.euiColorLightShade,
range: euiDarkVars.euiFocusBackgroundColor,
success: euiDarkVars.euiColorSuccess,
warning: euiDarkVars.euiColorWarning,
};
} else {
colors = {
danger: euiLightVars.euiColorDanger,
mean: euiLightVars.euiColorPrimary,
gray: euiLightVars.euiColorLightShade,
range: euiLightVars.euiFocusBackgroundColor,
success: euiLightVars.euiColorSuccess,
warning: euiLightVars.euiColorWarning,
};
}
const [lastRefresh, setLastRefresh] = useState<number>(Date.now());
useEffect(() => {
renderGlobalHelpControls();
setBadge(
@ -111,77 +84,36 @@ const Application = (props: UptimeAppProps) => {
);
}, [canSave, renderGlobalHelpControls, setBadge]);
useEffect(() => {
document.title = getTitle();
}, []);
const refreshApp = () => {
const refreshTime = Date.now();
setLastRefresh(refreshTime);
store.dispatch(triggerAppRefresh(refreshTime));
};
const [getUrlParams] = useUrlParams();
const initializeSettingsContextValues = (): UMSettingsContextValues => {
const {
autorefreshInterval,
autorefreshIsPaused,
dateRangeStart,
dateRangeEnd,
} = getUrlParams();
const absoluteStartDate = DateMath.parse(dateRangeStart);
const absoluteEndDate = DateMath.parse(dateRangeEnd);
return {
// TODO: extract these values to dedicated (and more sensible) constants
absoluteStartDate: absoluteStartDate ? absoluteStartDate.valueOf() : 0,
absoluteEndDate: absoluteEndDate ? absoluteEndDate.valueOf() : 1,
autorefreshInterval,
autorefreshIsPaused,
basePath,
colors,
dateRangeStart,
dateRangeEnd,
isApmAvailable,
isInfraAvailable,
isLogsAvailable,
refreshApp,
commonlyUsedRanges,
};
};
store.dispatch(setBasePath(basePath));
return (
<i18nCore.Context>
<ReduxProvider store={store}>
<KibanaContextProvider services={{ ...core, ...plugins }}>
<Router basename={routerBasename}>
<Route
path="/"
render={(rootRouteProps: RouteComponentProps) => {
return (
<ApolloProvider client={client}>
<UptimeRefreshContext.Provider value={{ lastRefresh, ...rootRouteProps }}>
<UptimeSettingsContext.Provider value={initializeSettingsContextValues()}>
<EuiPage className="app-wrapper-panel " data-test-subj="uptimeApp">
<main>
<PageRouter
autocomplete={plugins.data.autocomplete}
basePath={basePath}
setBreadcrumbs={setBreadcrumbs}
/>
</main>
</EuiPage>
</UptimeSettingsContext.Provider>
</UptimeRefreshContext.Provider>
</ApolloProvider>
);
}}
/>
</Router>
</KibanaContextProvider>
</ReduxProvider>
</i18nCore.Context>
<EuiErrorBoundary>
<i18nCore.Context>
<ReduxProvider store={store}>
<KibanaContextProvider services={{ ...core, ...plugins }}>
<Router basename={routerBasename}>
<ApolloProvider client={client}>
<UptimeRefreshContextProvider>
<UptimeSettingsContextProvider {...props}>
<UptimeThemeContextProvider darkMode={darkMode}>
<EuiPage className="app-wrapper-panel " data-test-subj="uptimeApp">
<main>
<PageRouter
autocomplete={plugins.data.autocomplete}
basePath={basePath}
setBreadcrumbs={setBreadcrumbs}
/>
</main>
</EuiPage>
</UptimeThemeContextProvider>
</UptimeSettingsContextProvider>
</UptimeRefreshContextProvider>
</ApolloProvider>
</Router>
</KibanaContextProvider>
</ReduxProvider>
</i18nCore.Context>
</EuiErrorBoundary>
);
};