Skip to content

Commit 4bf82c7

Browse files
authored
Merge pull request #18 from grafana/ismail/type-fixes-5
Removing loki specific code and making custom jest matchers available in the repo
2 parents 7961718 + 3b287b3 commit 4bf82c7

32 files changed

+979
-840
lines changed

.config/webpack/webpack.config.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,10 @@ const config = async (env): Promise<Configuration> => {
3737
'lodash',
3838
'jquery',
3939
'moment',
40-
'slate',
4140
'emotion',
4241
'@emotion/react',
4342
'@emotion/css',
4443
'prismjs',
45-
'slate-plain-serializer',
4644
'@grafana/slate-react',
4745
'react',
4846
'react-dom',
@@ -97,7 +95,7 @@ const config = async (env): Promise<Configuration> => {
9795
},
9896
{
9997
test: /\.css$/,
100-
use: ["style-loader", "css-loader"]
98+
use: ['style-loader', 'css-loader'],
10199
},
102100
{
103101
test: /\.s[ac]ss$/,
@@ -197,17 +195,16 @@ const config = async (env): Promise<Configuration> => {
197195
modules: [path.resolve(process.cwd(), 'src'), 'node_modules'],
198196
unsafeCache: true,
199197
},
200-
}
198+
};
201199

202-
if(isWSL()) {
200+
if (isWSL()) {
203201
baseConfig.watchOptions = {
204202
poll: 3000,
205203
ignored: /node_modules/,
206-
}}
207-
204+
};
205+
}
208206

209207
return baseConfig;
210-
211208
};
212209

213210
export default config;

jest-setup.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ import { TextEncoder, TextDecoder } from 'util';
44

55
global.TextEncoder = TextEncoder;
66
global.TextDecoder = TextDecoder;
7+
8+
import { matchers } from './src/gcopypaste/public/test/matchers';
9+
10+
expect.extend(matchers);

package.json

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"author": "Grafana",
1919
"license": "Apache-2.0",
2020
"devDependencies": {
21-
"@babel/core": "7.23.0",
2221
"@emotion/eslint-plugin": "11.11.0",
2322
"@grafana/e2e": "10.1.4",
2423
"@grafana/e2e-selectors": "10.1.4",
@@ -40,9 +39,9 @@
4039
"@types/ol-ext": "npm:@siedlerchr/types-ol-ext@3.2.0",
4140
"@types/pluralize": "0.0.30",
4241
"@types/prismjs": "1.26.0",
43-
"@types/react": "18.2.15",
44-
"@types/react-beautiful-dnd": "13.1.4",
45-
"@types/react-dom": "18.2.7",
42+
"@types/react": "18.2.29",
43+
"@types/react-beautiful-dnd": "13.1.6",
44+
"@types/react-dom": "18.2.14",
4645
"@types/react-highlight-words": "0.16.5",
4746
"@types/react-redux": "7.1.25",
4847
"@types/react-window": "1.8.7",
@@ -132,9 +131,5 @@
132131
"prettier@3.0.0": {
133132
"unplugged": true
134133
}
135-
},
136-
"resolutions": {
137-
"@types/slate": "0.47.11",
138-
"slate-dev-environment@^0.2.2": "patch:slate-dev-environment@npm:0.2.5#.yarn/patches/slate-dev-environment-npm-0.2.5-9aeb7da7b5.patch"
139134
}
140135
}

src/components/VariableQueryEditor.test.tsx

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

65
import { PrometheusDatasource } from '../datasource';
6+
import { selectOptionInTest } from '../gcopypaste/test/helpers/selectOptionInTest';
77
import PrometheusLanguageProvider from '../language_provider';
88
import { migrateVariableEditorBackToVariableSupport } from '../migrations/variableMigration';
99
import { PromVariableQuery, PromVariableQueryType, StandardPromVariableQuery } from '../types';

src/configuration/ConfigEditor.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { SIGV4ConnectionConfig } from '@grafana/aws-sdk';
33
import { DataSourcePluginOptionsEditorProps, GrafanaTheme2 } from '@grafana/data';
44
import { ConfigSection, DataSourceDescription } from '@grafana/experimental';
55
import { config } from '@grafana/runtime';
6-
import { Alert, DataSourceHttpSettings, FieldValidationMessage, useTheme2 } from '@grafana/ui';
7-
import React, { useRef } from 'react';
6+
import { Alert, FieldValidationMessage, useTheme2 } from '@grafana/ui';
7+
import React from 'react';
88

99
import { PromOptions } from '../types';
1010

@@ -13,7 +13,6 @@ import { DataSourcehttpSettingsOverhaul } from './DataSourceHttpSettingsOverhaul
1313
import { PromSettings } from './PromSettings';
1414
import { AdvancedHttpSettings } from './overhaul/AdvancedHttpSettings';
1515

16-
1716
export const PROM_CONFIG_LABEL_WIDTH = 30;
1817

1918
export type Props = DataSourcePluginOptionsEditorProps<PromOptions>;
@@ -29,7 +28,7 @@ export const ConfigEditor = (props: Props) => {
2928
<Alert title="Error" severity="error">
3029
Browser access mode in the Prometheus data source is no longer available. Switch to server access mode.
3130
</Alert>
32-
)}
31+
)}
3332
<DataSourceDescription
3433
dataSourceName="Prometheus"
3534
docsLink="https://grafana.com/docs/grafana/latest/datasources/prometheus/configure-prometheus-data-source/"
@@ -41,7 +40,7 @@ export const ConfigEditor = (props: Props) => {
4140
sigV4AuthToggleEnabled={config.sigV4AuthEnabled}
4241
renderSigV4Editor={<SIGV4ConnectionConfig {...props}></SIGV4ConnectionConfig>}
4342
secureSocksDSProxyEnabled={config.secureSocksDSProxyEnabled}
44-
/>
43+
/>
4544
<hr />
4645
<ConfigSection
4746
className={styles.advancedSettings}

src/datasource.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
toDataFrame,
1616
VariableHide,
1717
} from '@grafana/data';
18-
import { TemplateSrv } from 'app/features/templating/template_srv';
18+
import { TemplateSrv } from '@grafana/runtime';
1919
import { cloneDeep } from 'lodash';
2020
import { lastValueFrom, of, throwError } from 'rxjs';
2121

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { DataQuery } from '@grafana/data';
2+
3+
export const getNextRefIdChar = (queries: DataQuery[]): string => {
4+
for (let num = 0; ; num++) {
5+
const refId = getRefId(num);
6+
if (!queries.some((query) => query.refId === refId)) {
7+
return refId;
8+
}
9+
}
10+
};
11+
12+
function getRefId(num: number): string {
13+
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
14+
15+
if (num < letters.length) {
16+
return letters[num];
17+
} else {
18+
return getRefId(Math.floor(num / letters.length) - 1) + letters[num % letters.length];
19+
}
20+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Observable } from 'rxjs';
2+
3+
import { toEmitValues } from './toEmitValues';
4+
import { toEmitValuesWith } from './toEmitValuesWith';
5+
import { ObservableMatchers } from './types';
6+
7+
export const matchers: ObservableMatchers<void, Observable<any>> = {
8+
toEmitValues,
9+
toEmitValuesWith,
10+
};
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import { interval, Observable, of, throwError } from 'rxjs';
2+
import { map, mergeMap, take } from 'rxjs/operators';
3+
4+
import { OBSERVABLE_TEST_TIMEOUT_IN_MS } from './types';
5+
6+
describe('toEmitValues matcher', () => {
7+
describe('failing tests', () => {
8+
describe('passing null in expect', () => {
9+
it('should fail', async () => {
10+
const observable = null as unknown as Observable<number>;
11+
12+
const rejects = expect(() => expect(observable).toEmitValues([1, 2, 3])).rejects;
13+
await rejects.toThrow();
14+
});
15+
});
16+
17+
describe('passing undefined in expect', () => {
18+
it('should fail', async () => {
19+
const observable = undefined as unknown as Observable<number>;
20+
21+
const rejects = expect(() => expect(observable).toEmitValues([1, 2, 3])).rejects;
22+
await rejects.toThrow();
23+
});
24+
});
25+
26+
describe('passing number instead of Observable in expect', () => {
27+
it('should fail', async () => {
28+
const observable = 1 as unknown as Observable<number>;
29+
30+
const rejects = expect(() => expect(observable).toEmitValues([1, 2, 3])).rejects;
31+
await rejects.toThrow();
32+
});
33+
});
34+
35+
describe('wrong number of emitted values', () => {
36+
it('should fail', async () => {
37+
const observable = interval(10).pipe(take(3));
38+
39+
const rejects = expect(() => expect(observable).toEmitValues([0, 1])).rejects;
40+
await rejects.toThrow();
41+
});
42+
});
43+
44+
describe('wrong emitted values', () => {
45+
it('should fail', async () => {
46+
const observable = interval(10).pipe(take(3));
47+
48+
const rejects = expect(() => expect(observable).toEmitValues([1, 2, 3])).rejects;
49+
await rejects.toThrow();
50+
});
51+
});
52+
53+
describe('wrong emitted value types', () => {
54+
it('should fail', async () => {
55+
const observable = interval(10).pipe(take(3)) as unknown as Observable<string>;
56+
57+
const rejects = expect(() => expect(observable).toEmitValues(['0', '1', '2'])).rejects;
58+
await rejects.toThrow();
59+
});
60+
});
61+
62+
describe(`observable that does not complete within ${OBSERVABLE_TEST_TIMEOUT_IN_MS}ms`, () => {
63+
it('should fail', async () => {
64+
const observable = interval(600);
65+
66+
const rejects = expect(() => expect(observable).toEmitValues([0])).rejects;
67+
await rejects.toThrow();
68+
});
69+
});
70+
});
71+
72+
describe('passing tests', () => {
73+
describe('correct emitted values', () => {
74+
it('should pass with correct message', async () => {
75+
const observable = interval(10).pipe(take(3));
76+
await expect(observable).toEmitValues([0, 1, 2]);
77+
});
78+
});
79+
80+
describe('using nested arrays', () => {
81+
it('should pass with correct message', async () => {
82+
const observable = interval(10).pipe(
83+
map((interval) => [{ text: interval.toString(), value: interval }]),
84+
take(3)
85+
);
86+
await expect(observable).toEmitValues([
87+
[{ text: '0', value: 0 }],
88+
[{ text: '1', value: 1 }],
89+
[{ text: '2', value: 2 }],
90+
]);
91+
});
92+
});
93+
94+
describe('using nested objects', () => {
95+
it('should pass with correct message', async () => {
96+
const observable = interval(10).pipe(
97+
map((interval) => ({ inner: { text: interval.toString(), value: interval } })),
98+
take(3)
99+
);
100+
await expect(observable).toEmitValues([
101+
{ inner: { text: '0', value: 0 } },
102+
{ inner: { text: '1', value: 1 } },
103+
{ inner: { text: '2', value: 2 } },
104+
]);
105+
});
106+
});
107+
108+
describe('correct emitted values with throw', () => {
109+
it('should pass with correct message', async () => {
110+
const observable = interval(10).pipe(
111+
map((interval) => {
112+
if (interval > 1) {
113+
throw 'an error';
114+
}
115+
116+
return interval;
117+
})
118+
) as unknown as Observable<string | number>;
119+
120+
await expect(observable).toEmitValues([0, 1, 'an error']);
121+
});
122+
});
123+
124+
describe('correct emitted values with throwError', () => {
125+
it('should pass with correct message', async () => {
126+
const observable = interval(10).pipe(
127+
mergeMap((interval) => {
128+
if (interval === 1) {
129+
return throwError('an error');
130+
}
131+
132+
return of(interval);
133+
})
134+
) as unknown as Observable<string | number>;
135+
136+
await expect(observable).toEmitValues([0, 'an error']);
137+
});
138+
});
139+
});
140+
});

0 commit comments

Comments
 (0)