@oanda/labs-crowd-view-widget 1.0.50 → 1.0.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +420 -0
- package/dist/main/CrowdViewWidget/components/Chart/Chart.js +60 -21
- package/dist/main/CrowdViewWidget/components/Chart/Chart.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/ChartWithData.js +3 -3
- package/dist/main/CrowdViewWidget/components/Chart/ChartWithData.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/chartOptions.js +208 -42
- package/dist/main/CrowdViewWidget/components/Chart/chartOptions.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/types.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/useCrowdViewData.js +25 -6
- package/dist/main/CrowdViewWidget/components/Chart/useCrowdViewData.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/chartUtils.js +12 -10
- package/dist/main/CrowdViewWidget/components/Chart/utils/chartUtils.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/getChartStyles.js +27 -0
- package/dist/main/CrowdViewWidget/components/Chart/utils/getChartStyles.js.map +1 -0
- package/dist/main/CrowdViewWidget/components/Chart/utils/getGridLines.js +123 -0
- package/dist/main/CrowdViewWidget/components/Chart/utils/getGridLines.js.map +1 -0
- package/dist/main/CrowdViewWidget/components/Chart/utils/index.js +22 -0
- package/dist/main/CrowdViewWidget/components/Chart/utils/index.js.map +1 -1
- package/dist/main/CrowdViewWidget/components/Chart/utils/processSentiments.js +28 -0
- package/dist/main/CrowdViewWidget/components/Chart/utils/processSentiments.js.map +1 -0
- package/dist/main/CrowdViewWidget/components/Legend/Legend.js +1 -1
- package/dist/main/CrowdViewWidget/components/Legend/Legend.js.map +1 -1
- package/dist/main/CrowdViewWidget/constants.js +13 -3
- package/dist/main/CrowdViewWidget/constants.js.map +1 -1
- package/dist/main/gql/getSentiments.js +11 -0
- package/dist/main/gql/getSentiments.js.map +1 -0
- package/dist/main/gql/types/gql.js +2 -1
- package/dist/main/gql/types/gql.js.map +1 -1
- package/dist/main/gql/types/graphql.js +162 -1
- package/dist/main/gql/types/graphql.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/Chart.js +63 -24
- package/dist/module/CrowdViewWidget/components/Chart/Chart.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/ChartWithData.js +3 -3
- package/dist/module/CrowdViewWidget/components/Chart/ChartWithData.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/chartOptions.js +208 -43
- package/dist/module/CrowdViewWidget/components/Chart/chartOptions.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/types.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/useCrowdViewData.js +26 -7
- package/dist/module/CrowdViewWidget/components/Chart/useCrowdViewData.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/chartUtils.js +12 -10
- package/dist/module/CrowdViewWidget/components/Chart/utils/chartUtils.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/getChartStyles.js +20 -0
- package/dist/module/CrowdViewWidget/components/Chart/utils/getChartStyles.js.map +1 -0
- package/dist/module/CrowdViewWidget/components/Chart/utils/getGridLines.js +116 -0
- package/dist/module/CrowdViewWidget/components/Chart/utils/getGridLines.js.map +1 -0
- package/dist/module/CrowdViewWidget/components/Chart/utils/index.js +2 -0
- package/dist/module/CrowdViewWidget/components/Chart/utils/index.js.map +1 -1
- package/dist/module/CrowdViewWidget/components/Chart/utils/processSentiments.js +21 -0
- package/dist/module/CrowdViewWidget/components/Chart/utils/processSentiments.js.map +1 -0
- package/dist/module/CrowdViewWidget/components/Legend/Legend.js +1 -1
- package/dist/module/CrowdViewWidget/components/Legend/Legend.js.map +1 -1
- package/dist/module/CrowdViewWidget/constants.js +12 -2
- package/dist/module/CrowdViewWidget/constants.js.map +1 -1
- package/dist/module/gql/getSentiments.js +6 -0
- package/dist/module/gql/getSentiments.js.map +1 -0
- package/dist/module/gql/types/gql.js +2 -1
- package/dist/module/gql/types/gql.js.map +1 -1
- package/dist/module/gql/types/graphql.js +161 -0
- package/dist/module/gql/types/graphql.js.map +1 -1
- package/dist/types/CrowdViewWidget/components/Chart/types.d.ts +43 -0
- package/dist/types/CrowdViewWidget/components/Chart/utils/chartUtils.d.ts +2 -2
- package/dist/types/CrowdViewWidget/components/Chart/utils/getChartStyles.d.ts +10 -0
- package/dist/types/CrowdViewWidget/components/Chart/utils/getGridLines.d.ts +97 -0
- package/dist/types/CrowdViewWidget/components/Chart/utils/index.d.ts +2 -0
- package/dist/types/CrowdViewWidget/components/Chart/utils/processSentiments.d.ts +3 -0
- package/dist/types/CrowdViewWidget/constants.d.ts +11 -1
- package/dist/types/gql/getSentiments.d.ts +2 -0
- package/dist/types/gql/types/gql.d.ts +9 -0
- package/dist/types/gql/types/graphql.d.ts +36 -0
- package/package.json +3 -3
- package/src/CrowdViewWidget/components/Chart/Chart.tsx +86 -34
- package/src/CrowdViewWidget/components/Chart/ChartWithData.tsx +3 -3
- package/src/CrowdViewWidget/components/Chart/chartOptions.ts +242 -72
- package/src/CrowdViewWidget/components/Chart/types.ts +55 -0
- package/src/CrowdViewWidget/components/Chart/useCrowdViewData.ts +35 -3
- package/src/CrowdViewWidget/components/Chart/utils/chartUtils.ts +33 -14
- package/src/CrowdViewWidget/components/Chart/utils/getChartStyles.ts +42 -0
- package/src/CrowdViewWidget/components/Chart/utils/getGridLines.ts +148 -0
- package/src/CrowdViewWidget/components/Chart/utils/index.ts +2 -0
- package/src/CrowdViewWidget/components/Chart/utils/processSentiments.ts +42 -0
- package/src/CrowdViewWidget/components/Legend/Legend.tsx +1 -1
- package/src/CrowdViewWidget/constants.ts +17 -1
- package/src/gql/getSentiments.ts +25 -0
- package/src/gql/types/gql.ts +8 -0
- package/src/gql/types/graphql.ts +161 -0
- package/test/components/Chart/utils/chartUtils.test.ts +76 -2
- package/test/components/Chart/utils/getChartStyles.test.ts +64 -0
- package/test/components/Chart/utils/processSentiments.test.ts +130 -0
package/src/gql/types/graphql.ts
CHANGED
|
@@ -248,6 +248,7 @@ export type Query = {
|
|
|
248
248
|
resolveInstrumentsWithFilters?: Maybe<InstrumentTableResult>;
|
|
249
249
|
sentiment?: Maybe<Array<SentimentInstrument>>;
|
|
250
250
|
sentimentList?: Maybe<Array<SentimentInstrument>>;
|
|
251
|
+
sentiments: SentimentData;
|
|
251
252
|
topicalInstruments?: Maybe<Array<TopicalInstrument>>;
|
|
252
253
|
topicalInstrumentsCharts?: Maybe<Array<TopicalInstrumentChart>>;
|
|
253
254
|
topicalInstrumentsTotalCount: Scalars['Int']['output'];
|
|
@@ -342,6 +343,12 @@ export type QuerySentimentListArgs = {
|
|
|
342
343
|
sort?: InputMaybe<Sort>;
|
|
343
344
|
};
|
|
344
345
|
|
|
346
|
+
export type QuerySentimentsArgs = {
|
|
347
|
+
granularity: Granularity;
|
|
348
|
+
instrument: Scalars['String']['input'];
|
|
349
|
+
timeSpan: TimeSpan;
|
|
350
|
+
};
|
|
351
|
+
|
|
345
352
|
export type QueryTopicalInstrumentsArgs = {
|
|
346
353
|
assetClass?: InputMaybe<AssetClassName>;
|
|
347
354
|
count?: InputMaybe<Scalars['Int']['input']>;
|
|
@@ -395,6 +402,11 @@ export type Sentiment = {
|
|
|
395
402
|
shortPercent: Scalars['Float']['output'];
|
|
396
403
|
};
|
|
397
404
|
|
|
405
|
+
export type SentimentData = {
|
|
406
|
+
__typename?: 'SentimentData';
|
|
407
|
+
sentiments: Array<Maybe<SentimentWithTime>>;
|
|
408
|
+
};
|
|
409
|
+
|
|
398
410
|
export type SentimentInstrument = {
|
|
399
411
|
__typename?: 'SentimentInstrument';
|
|
400
412
|
displayName: Scalars['String']['output'];
|
|
@@ -403,6 +415,12 @@ export type SentimentInstrument = {
|
|
|
403
415
|
updatedAt: Scalars['String']['output'];
|
|
404
416
|
};
|
|
405
417
|
|
|
418
|
+
export type SentimentWithTime = {
|
|
419
|
+
__typename?: 'SentimentWithTime';
|
|
420
|
+
sentiment: Sentiment;
|
|
421
|
+
time: Scalars['String']['output'];
|
|
422
|
+
};
|
|
423
|
+
|
|
406
424
|
export enum Sort {
|
|
407
425
|
Bearish = 'BEARISH',
|
|
408
426
|
Bullish = 'BULLISH',
|
|
@@ -572,6 +590,28 @@ export type GetPriceCandlesQuery = {
|
|
|
572
590
|
};
|
|
573
591
|
};
|
|
574
592
|
|
|
593
|
+
export type GetSentimentsQueryVariables = Exact<{
|
|
594
|
+
instrument: Scalars['String']['input'];
|
|
595
|
+
granularity: Granularity;
|
|
596
|
+
timeSpan: TimeSpan;
|
|
597
|
+
}>;
|
|
598
|
+
|
|
599
|
+
export type GetSentimentsQuery = {
|
|
600
|
+
__typename?: 'Query';
|
|
601
|
+
sentiments: {
|
|
602
|
+
__typename?: 'SentimentData';
|
|
603
|
+
sentiments: Array<{
|
|
604
|
+
__typename?: 'SentimentWithTime';
|
|
605
|
+
time: string;
|
|
606
|
+
sentiment: {
|
|
607
|
+
__typename?: 'Sentiment';
|
|
608
|
+
longPercent: number;
|
|
609
|
+
shortPercent: number;
|
|
610
|
+
};
|
|
611
|
+
} | null>;
|
|
612
|
+
};
|
|
613
|
+
};
|
|
614
|
+
|
|
575
615
|
export const GetOrderPositionBooksDocument = {
|
|
576
616
|
kind: 'Document',
|
|
577
617
|
definitions: [
|
|
@@ -895,3 +935,124 @@ export const GetPriceCandlesDocument = {
|
|
|
895
935
|
GetPriceCandlesQuery,
|
|
896
936
|
GetPriceCandlesQueryVariables
|
|
897
937
|
>;
|
|
938
|
+
export const GetSentimentsDocument = {
|
|
939
|
+
kind: 'Document',
|
|
940
|
+
definitions: [
|
|
941
|
+
{
|
|
942
|
+
kind: 'OperationDefinition',
|
|
943
|
+
operation: 'query',
|
|
944
|
+
name: { kind: 'Name', value: 'GetSentiments' },
|
|
945
|
+
variableDefinitions: [
|
|
946
|
+
{
|
|
947
|
+
kind: 'VariableDefinition',
|
|
948
|
+
variable: {
|
|
949
|
+
kind: 'Variable',
|
|
950
|
+
name: { kind: 'Name', value: 'instrument' },
|
|
951
|
+
},
|
|
952
|
+
type: {
|
|
953
|
+
kind: 'NonNullType',
|
|
954
|
+
type: {
|
|
955
|
+
kind: 'NamedType',
|
|
956
|
+
name: { kind: 'Name', value: 'String' },
|
|
957
|
+
},
|
|
958
|
+
},
|
|
959
|
+
},
|
|
960
|
+
{
|
|
961
|
+
kind: 'VariableDefinition',
|
|
962
|
+
variable: {
|
|
963
|
+
kind: 'Variable',
|
|
964
|
+
name: { kind: 'Name', value: 'granularity' },
|
|
965
|
+
},
|
|
966
|
+
type: {
|
|
967
|
+
kind: 'NonNullType',
|
|
968
|
+
type: {
|
|
969
|
+
kind: 'NamedType',
|
|
970
|
+
name: { kind: 'Name', value: 'Granularity' },
|
|
971
|
+
},
|
|
972
|
+
},
|
|
973
|
+
},
|
|
974
|
+
{
|
|
975
|
+
kind: 'VariableDefinition',
|
|
976
|
+
variable: {
|
|
977
|
+
kind: 'Variable',
|
|
978
|
+
name: { kind: 'Name', value: 'timeSpan' },
|
|
979
|
+
},
|
|
980
|
+
type: {
|
|
981
|
+
kind: 'NonNullType',
|
|
982
|
+
type: {
|
|
983
|
+
kind: 'NamedType',
|
|
984
|
+
name: { kind: 'Name', value: 'TimeSpan' },
|
|
985
|
+
},
|
|
986
|
+
},
|
|
987
|
+
},
|
|
988
|
+
],
|
|
989
|
+
selectionSet: {
|
|
990
|
+
kind: 'SelectionSet',
|
|
991
|
+
selections: [
|
|
992
|
+
{
|
|
993
|
+
kind: 'Field',
|
|
994
|
+
name: { kind: 'Name', value: 'sentiments' },
|
|
995
|
+
arguments: [
|
|
996
|
+
{
|
|
997
|
+
kind: 'Argument',
|
|
998
|
+
name: { kind: 'Name', value: 'instrument' },
|
|
999
|
+
value: {
|
|
1000
|
+
kind: 'Variable',
|
|
1001
|
+
name: { kind: 'Name', value: 'instrument' },
|
|
1002
|
+
},
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
kind: 'Argument',
|
|
1006
|
+
name: { kind: 'Name', value: 'granularity' },
|
|
1007
|
+
value: {
|
|
1008
|
+
kind: 'Variable',
|
|
1009
|
+
name: { kind: 'Name', value: 'granularity' },
|
|
1010
|
+
},
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
kind: 'Argument',
|
|
1014
|
+
name: { kind: 'Name', value: 'timeSpan' },
|
|
1015
|
+
value: {
|
|
1016
|
+
kind: 'Variable',
|
|
1017
|
+
name: { kind: 'Name', value: 'timeSpan' },
|
|
1018
|
+
},
|
|
1019
|
+
},
|
|
1020
|
+
],
|
|
1021
|
+
selectionSet: {
|
|
1022
|
+
kind: 'SelectionSet',
|
|
1023
|
+
selections: [
|
|
1024
|
+
{
|
|
1025
|
+
kind: 'Field',
|
|
1026
|
+
name: { kind: 'Name', value: 'sentiments' },
|
|
1027
|
+
selectionSet: {
|
|
1028
|
+
kind: 'SelectionSet',
|
|
1029
|
+
selections: [
|
|
1030
|
+
{
|
|
1031
|
+
kind: 'Field',
|
|
1032
|
+
name: { kind: 'Name', value: 'sentiment' },
|
|
1033
|
+
selectionSet: {
|
|
1034
|
+
kind: 'SelectionSet',
|
|
1035
|
+
selections: [
|
|
1036
|
+
{
|
|
1037
|
+
kind: 'Field',
|
|
1038
|
+
name: { kind: 'Name', value: 'longPercent' },
|
|
1039
|
+
},
|
|
1040
|
+
{
|
|
1041
|
+
kind: 'Field',
|
|
1042
|
+
name: { kind: 'Name', value: 'shortPercent' },
|
|
1043
|
+
},
|
|
1044
|
+
],
|
|
1045
|
+
},
|
|
1046
|
+
},
|
|
1047
|
+
{ kind: 'Field', name: { kind: 'Name', value: 'time' } },
|
|
1048
|
+
],
|
|
1049
|
+
},
|
|
1050
|
+
},
|
|
1051
|
+
],
|
|
1052
|
+
},
|
|
1053
|
+
},
|
|
1054
|
+
],
|
|
1055
|
+
},
|
|
1056
|
+
},
|
|
1057
|
+
],
|
|
1058
|
+
} as unknown as DocumentNode<GetSentimentsQuery, GetSentimentsQueryVariables>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TooltipParam } from '../../../../src/CrowdViewWidget/components/Chart/types';
|
|
1
2
|
import {
|
|
2
3
|
formatXAxisLabel,
|
|
3
4
|
getLabelData,
|
|
@@ -137,12 +138,16 @@ describe('chartUtils', () => {
|
|
|
137
138
|
const labelCallback = (k: string) => k;
|
|
138
139
|
|
|
139
140
|
it('renders candle and book details when available', () => {
|
|
140
|
-
const params = [
|
|
141
|
+
const params: TooltipParam[] = [
|
|
141
142
|
{
|
|
143
|
+
seriesId: 'candlestick' as const,
|
|
142
144
|
axisValue: '2025-03-15T10:30:00Z',
|
|
143
145
|
value: [0, 1.11111, 1.22222, 1.00001, 1.33333],
|
|
144
146
|
},
|
|
145
|
-
{
|
|
147
|
+
{
|
|
148
|
+
seriesId: 'heatmap' as const,
|
|
149
|
+
value: ['2025-03-15T10:30:00Z', 1.33333, 0],
|
|
150
|
+
},
|
|
146
151
|
];
|
|
147
152
|
|
|
148
153
|
const buckets = [
|
|
@@ -161,6 +166,7 @@ describe('chartUtils', () => {
|
|
|
161
166
|
bookType: BookType.Order,
|
|
162
167
|
labelCallback,
|
|
163
168
|
});
|
|
169
|
+
expect(html).toBeDefined();
|
|
164
170
|
expect(html).toContain('candle');
|
|
165
171
|
expect(html).toContain('open_price');
|
|
166
172
|
expect(html).toContain('close_price');
|
|
@@ -171,5 +177,73 @@ describe('chartUtils', () => {
|
|
|
171
177
|
// Selected price 1.3306 falls into second bucket 1.3305 - 1.3310 which has negative sentiment
|
|
172
178
|
expect(html).toContain('sell_overbalance');
|
|
173
179
|
});
|
|
180
|
+
|
|
181
|
+
it('renders sentiment details when available', () => {
|
|
182
|
+
const params: TooltipParam[] = [
|
|
183
|
+
{
|
|
184
|
+
seriesId: 'candlestick' as const,
|
|
185
|
+
axisValue: '2025-03-15T10:30:00Z',
|
|
186
|
+
value: [0, 1.11111, 1.22222, 1.00001, 1.33333],
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
seriesId: 'sentiment' as const,
|
|
190
|
+
value: ['2025-03-15T10:30:00Z', 30.5, 69.5],
|
|
191
|
+
},
|
|
192
|
+
];
|
|
193
|
+
|
|
194
|
+
const buckets: never[] = [];
|
|
195
|
+
|
|
196
|
+
const html = getTooltipFormatter({
|
|
197
|
+
params,
|
|
198
|
+
buckets,
|
|
199
|
+
bucketWidth: 0.0005,
|
|
200
|
+
selectedPrice: 1.3306,
|
|
201
|
+
precision: 5,
|
|
202
|
+
bookType: BookType.Order,
|
|
203
|
+
labelCallback,
|
|
204
|
+
});
|
|
205
|
+
expect(html).toBeDefined();
|
|
206
|
+
expect(html).toContain('candle');
|
|
207
|
+
expect(html).toContain('sentiment');
|
|
208
|
+
expect(html).toContain('long');
|
|
209
|
+
expect(html).toContain('short');
|
|
210
|
+
expect(html).toContain('30.50');
|
|
211
|
+
expect(html).toContain('69.50');
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it('returns undefined when no candlestick param is provided', () => {
|
|
215
|
+
const params: TooltipParam[] = [
|
|
216
|
+
{
|
|
217
|
+
seriesId: 'heatmap' as const,
|
|
218
|
+
value: ['2025-03-15T10:30:00Z', 1.33333, 0],
|
|
219
|
+
},
|
|
220
|
+
];
|
|
221
|
+
|
|
222
|
+
const buckets: never[] = [];
|
|
223
|
+
|
|
224
|
+
const html = getTooltipFormatter({
|
|
225
|
+
params,
|
|
226
|
+
buckets,
|
|
227
|
+
bucketWidth: 0.0005,
|
|
228
|
+
selectedPrice: 1.3306,
|
|
229
|
+
precision: 5,
|
|
230
|
+
bookType: BookType.Order,
|
|
231
|
+
labelCallback,
|
|
232
|
+
});
|
|
233
|
+
expect(html).toBeUndefined();
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('returns undefined when params is empty', () => {
|
|
237
|
+
const html = getTooltipFormatter({
|
|
238
|
+
params: [],
|
|
239
|
+
buckets: [],
|
|
240
|
+
bucketWidth: 0.0005,
|
|
241
|
+
selectedPrice: 1.3306,
|
|
242
|
+
precision: 5,
|
|
243
|
+
bookType: BookType.Order,
|
|
244
|
+
labelCallback,
|
|
245
|
+
});
|
|
246
|
+
expect(html).toBeUndefined();
|
|
247
|
+
});
|
|
174
248
|
});
|
|
175
249
|
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { colorPalette } from '@oanda/labs-widget-common';
|
|
2
|
+
|
|
3
|
+
import { getChartStyles } from '../../../../src/CrowdViewWidget/components/Chart/utils/getChartStyles';
|
|
4
|
+
|
|
5
|
+
describe('getChartStyles', () => {
|
|
6
|
+
it('returns correct styles for dark mode', () => {
|
|
7
|
+
const styles = getChartStyles(true);
|
|
8
|
+
|
|
9
|
+
expect(styles.sentimentLongColor).toBe(colorPalette.darkBlue90);
|
|
10
|
+
expect(styles.sentimentShortColor).toBe(colorPalette.darkYellow90);
|
|
11
|
+
expect(styles.candleLongColor).toBe(colorPalette.bottleGreenDark);
|
|
12
|
+
expect(styles.candleShortColor).toBe(colorPalette.orange);
|
|
13
|
+
expect(styles.sentimentAreaOpacity).toBe(0.5);
|
|
14
|
+
expect(styles.tooltipLinesColor).toBe(colorPalette.orange);
|
|
15
|
+
expect(styles.sentimentLabelColor).toBe(colorPalette.white);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('returns correct styles for light mode', () => {
|
|
19
|
+
const styles = getChartStyles(false);
|
|
20
|
+
|
|
21
|
+
expect(styles.sentimentLongColor).toBe(colorPalette.lightBlue90);
|
|
22
|
+
expect(styles.sentimentShortColor).toBe(colorPalette.lightYellow90);
|
|
23
|
+
expect(styles.candleLongColor).toBe(colorPalette.bottleGreenLight);
|
|
24
|
+
expect(styles.candleShortColor).toBe(colorPalette.raspberryLight);
|
|
25
|
+
expect(styles.sentimentAreaOpacity).toBe(0.2);
|
|
26
|
+
expect(styles.tooltipLinesColor).toBe(colorPalette.bottleGreenLight);
|
|
27
|
+
expect(styles.sentimentLabelColor).toBe(colorPalette.black);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('returns all required style properties', () => {
|
|
31
|
+
const darkStyles = getChartStyles(true);
|
|
32
|
+
const lightStyles = getChartStyles(false);
|
|
33
|
+
|
|
34
|
+
const requiredProperties = [
|
|
35
|
+
'sentimentLongColor',
|
|
36
|
+
'sentimentShortColor',
|
|
37
|
+
'candleLongColor',
|
|
38
|
+
'candleShortColor',
|
|
39
|
+
'sentimentAreaOpacity',
|
|
40
|
+
'tooltipLinesColor',
|
|
41
|
+
'sentimentLabelColor',
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
requiredProperties.forEach((prop) => {
|
|
45
|
+
expect(darkStyles).toHaveProperty(prop);
|
|
46
|
+
expect(lightStyles).toHaveProperty(prop);
|
|
47
|
+
expect(typeof darkStyles[prop as keyof typeof darkStyles]).not.toBe(
|
|
48
|
+
'undefined'
|
|
49
|
+
);
|
|
50
|
+
expect(typeof lightStyles[prop as keyof typeof lightStyles]).not.toBe(
|
|
51
|
+
'undefined'
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('returns different opacity values for dark and light modes', () => {
|
|
57
|
+
const darkStyles = getChartStyles(true);
|
|
58
|
+
const lightStyles = getChartStyles(false);
|
|
59
|
+
|
|
60
|
+
expect(darkStyles.sentimentAreaOpacity).toBeGreaterThan(
|
|
61
|
+
lightStyles.sentimentAreaOpacity
|
|
62
|
+
);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { processSentiments } from '../../../../src/CrowdViewWidget/components/Chart/utils/processSentiments';
|
|
2
|
+
import type { GetSentimentsQuery } from '../../../../src/gql/types/graphql';
|
|
3
|
+
|
|
4
|
+
describe('processSentiments', () => {
|
|
5
|
+
it('returns empty array when sentimentsData is undefined', () => {
|
|
6
|
+
const result = processSentiments(undefined, ['2025-03-15T10:30:00Z']);
|
|
7
|
+
expect(result).toEqual([]);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('returns empty array when sentiments array is empty', () => {
|
|
11
|
+
const sentimentsData: GetSentimentsQuery = {
|
|
12
|
+
sentiments: {
|
|
13
|
+
sentiments: [],
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
const result = processSentiments(sentimentsData, ['2025-03-15T10:30:00Z']);
|
|
17
|
+
expect(result).toEqual([]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('returns empty array when sentiments is null', () => {
|
|
21
|
+
const sentimentsData: GetSentimentsQuery = {
|
|
22
|
+
sentiments: {
|
|
23
|
+
sentiments: null as never,
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
const result = processSentiments(sentimentsData, ['2025-03-15T10:30:00Z']);
|
|
27
|
+
expect(result).toEqual([]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('processes sentiments and matches with xAxisData', () => {
|
|
31
|
+
const xAxisData = [
|
|
32
|
+
'2025-03-15T10:30:00Z',
|
|
33
|
+
'2025-03-15T11:30:00Z',
|
|
34
|
+
'2025-03-15T12:30:00Z',
|
|
35
|
+
];
|
|
36
|
+
const sentimentsData: GetSentimentsQuery = {
|
|
37
|
+
sentiments: {
|
|
38
|
+
sentiments: [
|
|
39
|
+
{
|
|
40
|
+
time: '2025-03-15T10:30:00Z',
|
|
41
|
+
sentiment: {
|
|
42
|
+
shortPercent: 30.5,
|
|
43
|
+
longPercent: 69.5,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
time: '2025-03-15T11:30:00Z',
|
|
48
|
+
sentiment: {
|
|
49
|
+
shortPercent: 40.2,
|
|
50
|
+
longPercent: 59.8,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const result = processSentiments(sentimentsData, xAxisData);
|
|
58
|
+
expect(result).toEqual([
|
|
59
|
+
['2025-03-15T10:30:00Z', 30.5, 69.5],
|
|
60
|
+
['2025-03-15T11:30:00Z', 40.2, 59.8],
|
|
61
|
+
]);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('filters out sentiments that do not match xAxisData', () => {
|
|
65
|
+
const xAxisData = ['2025-03-15T10:30:00Z', '2025-03-15T11:30:00Z'];
|
|
66
|
+
const sentimentsData: GetSentimentsQuery = {
|
|
67
|
+
sentiments: {
|
|
68
|
+
sentiments: [
|
|
69
|
+
{
|
|
70
|
+
time: '2025-03-15T10:30:00Z',
|
|
71
|
+
sentiment: {
|
|
72
|
+
shortPercent: 30.5,
|
|
73
|
+
longPercent: 69.5,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
time: '2025-03-15T12:30:00Z', // Not in xAxisData
|
|
78
|
+
sentiment: {
|
|
79
|
+
shortPercent: 50.0,
|
|
80
|
+
longPercent: 50.0,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const result = processSentiments(sentimentsData, xAxisData);
|
|
88
|
+
expect(result).toEqual([['2025-03-15T10:30:00Z', 30.5, 69.5]]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('filters out sentiments with missing values', () => {
|
|
92
|
+
const xAxisData = ['2025-03-15T10:30:00Z'];
|
|
93
|
+
const sentimentsData: GetSentimentsQuery = {
|
|
94
|
+
sentiments: {
|
|
95
|
+
sentiments: [
|
|
96
|
+
{
|
|
97
|
+
time: '2025-03-15T10:30:00Z',
|
|
98
|
+
sentiment: {
|
|
99
|
+
shortPercent: null as never,
|
|
100
|
+
longPercent: null as never,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const result = processSentiments(sentimentsData, xAxisData);
|
|
108
|
+
expect(result).toEqual([]);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('returns empty array when no sentiments match xAxisData', () => {
|
|
112
|
+
const xAxisData = ['2025-03-15T10:30:00Z'];
|
|
113
|
+
const sentimentsData: GetSentimentsQuery = {
|
|
114
|
+
sentiments: {
|
|
115
|
+
sentiments: [
|
|
116
|
+
{
|
|
117
|
+
time: '2025-03-15T11:30:00Z',
|
|
118
|
+
sentiment: {
|
|
119
|
+
shortPercent: 30.5,
|
|
120
|
+
longPercent: 69.5,
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const result = processSentiments(sentimentsData, xAxisData);
|
|
128
|
+
expect(result).toEqual([]);
|
|
129
|
+
});
|
|
130
|
+
});
|