Skip to content

Commit f723ff3

Browse files
authored
Merge pull request #14 from grafana/ismail/more-type-fixes-4
More type fixes
2 parents bb5f8be + 60d26ca commit f723ff3

File tree

9 files changed

+152
-8
lines changed

9 files changed

+152
-8
lines changed

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,23 @@
3131
"@testing-library/jest-dom": "5.16.5",
3232
"@testing-library/react": "14.0.0",
3333
"@testing-library/user-event": "14.4.3",
34+
"@types/d3": "7.4.0",
3435
"@types/debounce-promise": "3.1.7",
36+
"@types/eslint": "8.44.0",
3537
"@types/jest": "29.5.5",
3638
"@types/lodash": "4.14.199",
37-
"@types/d3": "7.4.0",
3839
"@types/node": "20.8.2",
3940
"@types/pluralize": "0.0.30",
4041
"@types/prismjs": "1.26.0",
41-
"@types/eslint": "8.44.0",
4242
"@types/react": "18.2.15",
43-
"@types/slate": "0.47.11",
44-
"@types/slate-plain-serializer": "0.7.2",
45-
"@types/slate-react": "0.22.9",
4643
"@types/react-beautiful-dnd": "13.1.4",
4744
"@types/react-dom": "18.2.7",
4845
"@types/react-highlight-words": "0.16.5",
4946
"@types/react-redux": "7.1.25",
5047
"@types/semver": "7.5.0",
48+
"@types/slate": "0.47.11",
49+
"@types/slate-plain-serializer": "0.7.2",
50+
"@types/slate-react": "0.22.9",
5151
"@types/testing-library__jest-dom": "5.14.8",
5252
"@types/uuid": "9.0.2",
5353
"@typescript-eslint/eslint-plugin": "5.42.0",
@@ -76,6 +76,7 @@
7676
"sass-loader": "13.3.2",
7777
"style-loader": "3.3.3",
7878
"swc-loader": "0.2.3",
79+
"testing-library-selector": "0.3.1",
7980
"ts-node": "10.9.1",
8081
"tsconfig-paths": "4.2.0",
8182
"typescript": "4.8.4",
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React, { useEffect, useState } from 'react';
2+
3+
import store from '../../store';
4+
5+
export interface Props<T> {
6+
storageKey: string;
7+
defaultValue: T;
8+
children: (value: T, onSaveToStore: (value: T) => void, onDeleteFromStore: () => void) => React.ReactNode;
9+
}
10+
11+
export const LocalStorageValueProvider = <T,>(props: Props<T>) => {
12+
const { children, storageKey, defaultValue } = props;
13+
14+
const [state, setState] = useState({ value: store.getObject(props.storageKey, props.defaultValue) });
15+
16+
useEffect(() => {
17+
const onStorageUpdate = (v: StorageEvent) => {
18+
if (v.key === storageKey) {
19+
setState({ value: store.getObject(props.storageKey, props.defaultValue) });
20+
}
21+
};
22+
23+
window.addEventListener('storage', onStorageUpdate);
24+
25+
return () => {
26+
window.removeEventListener('storage', onStorageUpdate);
27+
};
28+
});
29+
30+
const onSaveToStore = (value: T) => {
31+
try {
32+
store.setObject(storageKey, value);
33+
} catch (error) {
34+
console.error(error);
35+
}
36+
setState({ value });
37+
};
38+
39+
const onDeleteFromStore = () => {
40+
try {
41+
store.delete(storageKey);
42+
} catch (error) {
43+
console.log(error);
44+
}
45+
setState({ value: defaultValue });
46+
};
47+
48+
return <>{children(state.value, onSaveToStore, onDeleteFromStore)}</>;
49+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { LocalStorageValueProvider } from './LocalStorageValueProvider';

src/gcopypaste/app/core/store.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
type StoreValue = string | number | boolean | null;
2+
3+
export class Store {
4+
get(key: string) {
5+
return window.localStorage[key];
6+
}
7+
8+
set(key: string, value: StoreValue) {
9+
window.localStorage[key] = value;
10+
}
11+
12+
getBool(key: string, def: boolean): boolean {
13+
if (def !== void 0 && !this.exists(key)) {
14+
return def;
15+
}
16+
return window.localStorage[key] === 'true';
17+
}
18+
19+
getObject<T = unknown>(key: string): T | undefined;
20+
getObject<T = unknown>(key: string, def: T): T;
21+
getObject<T = unknown>(key: string, def?: T) {
22+
let ret = def;
23+
if (this.exists(key)) {
24+
const json = window.localStorage[key];
25+
try {
26+
ret = JSON.parse(json);
27+
} catch (error) {
28+
console.error(`Error parsing store object: ${key}. Returning default: ${def}. [${error}]`);
29+
}
30+
}
31+
return ret;
32+
}
33+
34+
/* Returns true when successfully stored, throws error if not successfully stored */
35+
setObject(key: string, value: unknown) {
36+
let json;
37+
try {
38+
json = JSON.stringify(value);
39+
} catch (error) {
40+
throw new Error(`Could not stringify object: ${key}. [${error}]`);
41+
}
42+
try {
43+
this.set(key, json);
44+
} catch (error) {
45+
// Likely hitting storage quota
46+
const errorToThrow = new Error(`Could not save item in localStorage: ${key}. [${error}]`);
47+
if (error instanceof Error) {
48+
errorToThrow.name = error.name;
49+
}
50+
throw errorToThrow;
51+
}
52+
return true;
53+
}
54+
55+
exists(key: string) {
56+
return window.localStorage[key] !== void 0;
57+
}
58+
59+
delete(key: string) {
60+
window.localStorage.removeItem(key);
61+
}
62+
}
63+
64+
const store = new Store();
65+
export default store;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Matcher, waitFor } from '@testing-library/react';
2+
import userEvent from '@testing-library/user-event';
3+
import { select } from 'react-select-event';
4+
import { byRole } from 'testing-library-selector';
5+
6+
// Used to select an option or options from a Select in unit tests
7+
export const selectOptionInTest = async (
8+
input: HTMLElement,
9+
optionOrOptions: string | RegExp | Array<string | RegExp>
10+
) => await waitFor(() => select(input, optionOrOptions, { container: document.body }));
11+
12+
// Finds the parent of the Select so you can assert if it has a value
13+
export const getSelectParent = (input: HTMLElement) =>
14+
input.parentElement?.parentElement?.parentElement?.parentElement?.parentElement;
15+
16+
export const clickSelectOption = async (selectElement: HTMLElement, optionText: string): Promise<void> => {
17+
await userEvent.click(byRole('combobox').get(selectElement));
18+
await selectOptionInTest(selectElement, optionText);
19+
};
20+
export const clickSelectOptionMatch = async (selectElement: HTMLElement, optionText: Matcher): Promise<void> => {
21+
await userEvent.click(byRole('combobox').get(selectElement));
22+
await selectOptionInTest(selectElement, optionText as string);
23+
};

src/querybuilder/components/LabelFilters.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { render, screen } from '@testing-library/react';
22
import userEvent from '@testing-library/user-event';
33
import React, { ComponentProps } from 'react';
4-
import { selectOptionInTest } from 'test/helpers/selectOptionInTest';
54

5+
import { selectOptionInTest } from '../../gcopypaste/test/helpers/selectOptionInTest';
66
import { getLabelSelects } from '../testUtils';
77

88
import { LabelFilters, MISSING_LABEL_FILTER_ERROR_MESSAGE, Props } from './LabelFilters';

src/querybuilder/state.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CoreApp } from '@grafana/data';
2-
import store from 'app/core/store';
32

3+
import store from '../gcopypaste/app/core/store';
44
import { LegendFormatMode, PromQuery } from '../types';
55

66
import { QueryEditorMode } from './shared/types';

src/querycache/QueryCache.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import {
1010
} from '@grafana/data';
1111
import { faro } from '@grafana/faro-web-sdk';
1212
import { config, reportInteraction } from '@grafana/runtime';
13-
import { amendTable, Table, trimTable } from 'app/features/live/data/amendTimeSeries';
1413

14+
import { amendTable, Table, trimTable } from '../gcopypaste/app/features/live/data/amendTimeSeries';
1515
import { PromQuery } from '../types';
1616

1717
// dashboardUID + panelId + refId

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10085,6 +10085,11 @@ test-exclude@^6.0.0:
1008510085
glob "^7.1.4"
1008610086
minimatch "^3.0.4"
1008710087

10088+
testing-library-selector@0.3.1:
10089+
version "0.3.1"
10090+
resolved "https://registry.yarnpkg.com/testing-library-selector/-/testing-library-selector-0.3.1.tgz#ef4c2dfef356d7e0e1de458250d8311dae08af77"
10091+
integrity sha512-DjXyUhY/omIQNXnjOBFpkRaLADlf9yWDAW0KYpuNuurlS4aJNd1cE7yGG1XAH/LaMOSJ8woCkKdcO2UzyDAYQw==
10092+
1008810093
text-table@^0.2.0:
1008910094
version "0.2.0"
1009010095
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"

0 commit comments

Comments
 (0)