@oanda/labs-instruments-table-widget 1.0.43 → 1.0.45
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 +364 -0
- package/dist/main/InstrumentsTableWidget/InstrumentsTableWidget.js +4 -3
- package/dist/main/InstrumentsTableWidget/InstrumentsTableWidget.js.map +1 -1
- package/dist/main/InstrumentsTableWidget/Main.js +25 -21
- package/dist/main/InstrumentsTableWidget/Main.js.map +1 -1
- package/dist/main/InstrumentsTableWidget/config.js +7 -0
- package/dist/main/InstrumentsTableWidget/config.js.map +1 -1
- package/dist/main/InstrumentsTableWidget/constant.js +2 -1
- package/dist/main/InstrumentsTableWidget/constant.js.map +1 -1
- package/dist/main/InstrumentsTableWidget/types.js.map +1 -1
- package/dist/main/InstrumentsTableWidget/utils.js +21 -15
- package/dist/main/InstrumentsTableWidget/utils.js.map +1 -1
- package/dist/main/gql/resolveInstrumentsWithFilters.js +1 -1
- package/dist/main/gql/resolveInstrumentsWithFilters.js.map +1 -1
- package/dist/main/gql/types/gql.js +1 -1
- package/dist/main/gql/types/gql.js.map +1 -1
- package/dist/main/gql/types/graphql.js +6 -0
- package/dist/main/gql/types/graphql.js.map +1 -1
- package/dist/module/InstrumentsTableWidget/InstrumentsTableWidget.js +4 -3
- package/dist/module/InstrumentsTableWidget/InstrumentsTableWidget.js.map +1 -1
- package/dist/module/InstrumentsTableWidget/Main.js +27 -23
- package/dist/module/InstrumentsTableWidget/Main.js.map +1 -1
- package/dist/module/InstrumentsTableWidget/config.js +7 -0
- package/dist/module/InstrumentsTableWidget/config.js.map +1 -1
- package/dist/module/InstrumentsTableWidget/constant.js +2 -1
- package/dist/module/InstrumentsTableWidget/constant.js.map +1 -1
- package/dist/module/InstrumentsTableWidget/types.js.map +1 -1
- package/dist/module/InstrumentsTableWidget/utils.js +21 -15
- package/dist/module/InstrumentsTableWidget/utils.js.map +1 -1
- package/dist/module/gql/resolveInstrumentsWithFilters.js +1 -1
- package/dist/module/gql/resolveInstrumentsWithFilters.js.map +1 -1
- package/dist/module/gql/types/gql.js +1 -1
- package/dist/module/gql/types/gql.js.map +1 -1
- package/dist/module/gql/types/graphql.js +6 -0
- package/dist/module/gql/types/graphql.js.map +1 -1
- package/dist/types/InstrumentsTableWidget/Main.d.ts +2 -2
- package/dist/types/InstrumentsTableWidget/constant.d.ts +2 -1
- package/dist/types/InstrumentsTableWidget/types.d.ts +1 -0
- package/dist/types/InstrumentsTableWidget/utils.d.ts +7 -5
- package/dist/types/gql/types/gql.d.ts +2 -2
- package/dist/types/gql/types/graphql.d.ts +1 -0
- package/package.json +3 -3
- package/src/InstrumentsTableWidget/InstrumentsTableWidget.tsx +3 -6
- package/src/InstrumentsTableWidget/Main.tsx +33 -10
- package/src/InstrumentsTableWidget/config.ts +7 -0
- package/src/InstrumentsTableWidget/constant.ts +2 -0
- package/src/InstrumentsTableWidget/types.ts +1 -0
- package/src/InstrumentsTableWidget/utils.ts +29 -19
- package/src/gql/resolveInstrumentsWithFilters.ts +1 -0
- package/src/gql/types/gql.ts +3 -3
- package/src/gql/types/graphql.ts +5 -0
- package/test/utils.test.ts +255 -30
|
@@ -79,6 +79,13 @@ const normal: HeaderConfigType = {
|
|
|
79
79
|
minWidth: '80px',
|
|
80
80
|
},
|
|
81
81
|
},
|
|
82
|
+
[DataRecordType.DATA_SOURCE]: {
|
|
83
|
+
displayName: 'Data Source',
|
|
84
|
+
additionalStyles: {
|
|
85
|
+
align: 'right',
|
|
86
|
+
minWidth: '80px',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
82
89
|
};
|
|
83
90
|
|
|
84
91
|
const longInstruments: HeaderConfigType = {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DataRecordType } from '@oanda/labs-widget-common';
|
|
2
2
|
|
|
3
|
+
const RAW_PRICE_DIVISION = 'MKTD';
|
|
3
4
|
const DEFAULT_COUNT = 10;
|
|
4
5
|
|
|
5
6
|
const DEFAULT_TOTAL_COUNT = 50;
|
|
@@ -20,4 +21,5 @@ export {
|
|
|
20
21
|
DEFAULT_COUNT,
|
|
21
22
|
DEFAULT_TOTAL_COUNT,
|
|
22
23
|
INSTRUMENT_TOOLTIP_ID,
|
|
24
|
+
RAW_PRICE_DIVISION,
|
|
23
25
|
};
|
|
@@ -1,24 +1,34 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DataRecord } from '@oanda/labs-widget-common';
|
|
2
2
|
|
|
3
|
-
import { DataSource
|
|
4
|
-
import { PriceType } from './types';
|
|
3
|
+
import { DataSource } from '../gql/types/graphql';
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
},
|
|
16
|
-
[PriceType.Division]: {
|
|
17
|
-
[DataSource.Mt5]: division,
|
|
18
|
-
[DataSource.V20]: division,
|
|
19
|
-
},
|
|
5
|
+
interface GroupedNames {
|
|
6
|
+
v20instruments: string[];
|
|
7
|
+
mt5instruments: string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const groupNamesBySource = (items: DataRecord[]) => {
|
|
11
|
+
const initialState: GroupedNames = {
|
|
12
|
+
v20instruments: [],
|
|
13
|
+
mt5instruments: [],
|
|
20
14
|
};
|
|
21
|
-
|
|
15
|
+
|
|
16
|
+
return items.reduce((accumulator, currentItem) => {
|
|
17
|
+
if (currentItem.dataSource === DataSource.Mt5) {
|
|
18
|
+
return {
|
|
19
|
+
v20instruments: accumulator.v20instruments,
|
|
20
|
+
mt5instruments: [...accumulator.mt5instruments, currentItem.instrument],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
if (currentItem.dataSource === DataSource.V20) {
|
|
24
|
+
return {
|
|
25
|
+
v20instruments: [...accumulator.v20instruments, currentItem.instrument],
|
|
26
|
+
mt5instruments: accumulator.mt5instruments,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return accumulator;
|
|
31
|
+
}, initialState);
|
|
22
32
|
};
|
|
23
33
|
|
|
24
|
-
export {
|
|
34
|
+
export { groupNamesBySource };
|
package/src/gql/types/gql.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/
|
|
|
13
13
|
* Therefore it is highly recommended to use the babel or swc plugin for production.
|
|
14
14
|
*/
|
|
15
15
|
const documents = {
|
|
16
|
-
'\n query resolveInstrumentsWithFilters(\n $division: Division!\n $assetClass: [AssetClassName]\n $dataSource: DataSource!\n $instruments: [String]\n $searchPattern: String\n $tradeModes: [TradeMode]\n $count: Int\n $offset: Int\n $withTradingModes: Boolean!\n ) {\n resolveInstrumentsWithFilters(\n division: $division\n assetClass: $assetClass\n dataSource: $dataSource\n instruments: $instruments\n searchPattern: $searchPattern\n count: $count\n offset: $offset\n tradeModes: $tradeModes\n ) {\n instruments {\n name\n displayName\n tradeMode @include(if: $withTradingModes)\n }\n totalCount\n updatedAt @include(if: $withTradingModes)\n }\n }\n':
|
|
16
|
+
'\n query resolveInstrumentsWithFilters(\n $division: Division!\n $assetClass: [AssetClassName]\n $dataSource: DataSource!\n $instruments: [String]\n $searchPattern: String\n $tradeModes: [TradeMode]\n $count: Int\n $offset: Int\n $withTradingModes: Boolean!\n ) {\n resolveInstrumentsWithFilters(\n division: $division\n assetClass: $assetClass\n dataSource: $dataSource\n instruments: $instruments\n searchPattern: $searchPattern\n count: $count\n offset: $offset\n tradeModes: $tradeModes\n ) {\n instruments {\n name\n displayName\n tradeMode @include(if: $withTradingModes)\n dataSource\n }\n totalCount\n updatedAt @include(if: $withTradingModes)\n }\n }\n':
|
|
17
17
|
types.ResolveInstrumentsWithFiltersDocument,
|
|
18
18
|
};
|
|
19
19
|
|
|
@@ -35,8 +35,8 @@ export function graphql(source: string): unknown;
|
|
|
35
35
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
36
36
|
*/
|
|
37
37
|
export function graphql(
|
|
38
|
-
source: '\n query resolveInstrumentsWithFilters(\n $division: Division!\n $assetClass: [AssetClassName]\n $dataSource: DataSource!\n $instruments: [String]\n $searchPattern: String\n $tradeModes: [TradeMode]\n $count: Int\n $offset: Int\n $withTradingModes: Boolean!\n ) {\n resolveInstrumentsWithFilters(\n division: $division\n assetClass: $assetClass\n dataSource: $dataSource\n instruments: $instruments\n searchPattern: $searchPattern\n count: $count\n offset: $offset\n tradeModes: $tradeModes\n ) {\n instruments {\n name\n displayName\n tradeMode @include(if: $withTradingModes)\n }\n totalCount\n updatedAt @include(if: $withTradingModes)\n }\n }\n'
|
|
39
|
-
): (typeof documents)['\n query resolveInstrumentsWithFilters(\n $division: Division!\n $assetClass: [AssetClassName]\n $dataSource: DataSource!\n $instruments: [String]\n $searchPattern: String\n $tradeModes: [TradeMode]\n $count: Int\n $offset: Int\n $withTradingModes: Boolean!\n ) {\n resolveInstrumentsWithFilters(\n division: $division\n assetClass: $assetClass\n dataSource: $dataSource\n instruments: $instruments\n searchPattern: $searchPattern\n count: $count\n offset: $offset\n tradeModes: $tradeModes\n ) {\n instruments {\n name\n displayName\n tradeMode @include(if: $withTradingModes)\n }\n totalCount\n updatedAt @include(if: $withTradingModes)\n }\n }\n'];
|
|
38
|
+
source: '\n query resolveInstrumentsWithFilters(\n $division: Division!\n $assetClass: [AssetClassName]\n $dataSource: DataSource!\n $instruments: [String]\n $searchPattern: String\n $tradeModes: [TradeMode]\n $count: Int\n $offset: Int\n $withTradingModes: Boolean!\n ) {\n resolveInstrumentsWithFilters(\n division: $division\n assetClass: $assetClass\n dataSource: $dataSource\n instruments: $instruments\n searchPattern: $searchPattern\n count: $count\n offset: $offset\n tradeModes: $tradeModes\n ) {\n instruments {\n name\n displayName\n tradeMode @include(if: $withTradingModes)\n dataSource\n }\n totalCount\n updatedAt @include(if: $withTradingModes)\n }\n }\n'
|
|
39
|
+
): (typeof documents)['\n query resolveInstrumentsWithFilters(\n $division: Division!\n $assetClass: [AssetClassName]\n $dataSource: DataSource!\n $instruments: [String]\n $searchPattern: String\n $tradeModes: [TradeMode]\n $count: Int\n $offset: Int\n $withTradingModes: Boolean!\n ) {\n resolveInstrumentsWithFilters(\n division: $division\n assetClass: $assetClass\n dataSource: $dataSource\n instruments: $instruments\n searchPattern: $searchPattern\n count: $count\n offset: $offset\n tradeModes: $tradeModes\n ) {\n instruments {\n name\n displayName\n tradeMode @include(if: $withTradingModes)\n dataSource\n }\n totalCount\n updatedAt @include(if: $withTradingModes)\n }\n }\n'];
|
|
40
40
|
|
|
41
41
|
export function graphql(source: string) {
|
|
42
42
|
return (documents as any)[source] ?? {};
|
package/src/gql/types/graphql.ts
CHANGED
|
@@ -551,6 +551,7 @@ export type ResolveInstrumentsWithFiltersQuery = {
|
|
|
551
551
|
name: string;
|
|
552
552
|
displayName: string;
|
|
553
553
|
tradeMode?: TradeMode;
|
|
554
|
+
dataSource: DataSource;
|
|
554
555
|
}>;
|
|
555
556
|
} | null;
|
|
556
557
|
};
|
|
@@ -781,6 +782,10 @@ export const ResolveInstrumentsWithFiltersDocument = {
|
|
|
781
782
|
},
|
|
782
783
|
],
|
|
783
784
|
},
|
|
785
|
+
{
|
|
786
|
+
kind: 'Field',
|
|
787
|
+
name: { kind: 'Name', value: 'dataSource' },
|
|
788
|
+
},
|
|
784
789
|
],
|
|
785
790
|
},
|
|
786
791
|
},
|
package/test/utils.test.ts
CHANGED
|
@@ -1,32 +1,257 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
)
|
|
1
|
+
import { DataSource } from '../src/gql/types/graphql';
|
|
2
|
+
import { groupNamesBySource } from '../src/InstrumentsTableWidget/utils';
|
|
3
|
+
|
|
4
|
+
describe('groupNamesBySource', () => {
|
|
5
|
+
it('should return empty arrays for both sources when given empty input', () => {
|
|
6
|
+
const result = groupNamesBySource([]);
|
|
7
|
+
|
|
8
|
+
expect(result).toEqual({
|
|
9
|
+
v20instruments: [],
|
|
10
|
+
mt5instruments: [],
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should group V20 instruments correctly', () => {
|
|
15
|
+
const items = [
|
|
16
|
+
{
|
|
17
|
+
instrument: 'EUR_USD',
|
|
18
|
+
displayName: 'EUR/USD',
|
|
19
|
+
dataSource: DataSource.V20,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
instrument: 'GBP_USD',
|
|
23
|
+
displayName: 'GBP/USD',
|
|
24
|
+
dataSource: DataSource.V20,
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
const result = groupNamesBySource(items);
|
|
29
|
+
|
|
30
|
+
expect(result).toEqual({
|
|
31
|
+
v20instruments: ['EUR_USD', 'GBP_USD'],
|
|
32
|
+
mt5instruments: [],
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should group MT5 instruments correctly', () => {
|
|
37
|
+
const items = [
|
|
38
|
+
{
|
|
39
|
+
instrument: 'EUR_USD_CFD',
|
|
40
|
+
displayName: 'EUR/USD CFD',
|
|
41
|
+
dataSource: DataSource.Mt5,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
instrument: 'GBP_USD_CFD',
|
|
45
|
+
displayName: 'GBP/USD CFD',
|
|
46
|
+
dataSource: DataSource.Mt5,
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const result = groupNamesBySource(items);
|
|
51
|
+
|
|
52
|
+
expect(result).toEqual({
|
|
53
|
+
v20instruments: [],
|
|
54
|
+
mt5instruments: ['EUR_USD_CFD', 'GBP_USD_CFD'],
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should group mixed V20 and MT5 instruments correctly', () => {
|
|
59
|
+
const items = [
|
|
60
|
+
{
|
|
61
|
+
instrument: 'EUR_USD',
|
|
62
|
+
displayName: 'EUR/USD',
|
|
63
|
+
dataSource: DataSource.V20,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
instrument: 'GBP_USD_CFD',
|
|
67
|
+
displayName: 'GBP/USD CFD',
|
|
68
|
+
dataSource: DataSource.Mt5,
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
instrument: 'USD_JPY',
|
|
72
|
+
displayName: 'USD/JPY',
|
|
73
|
+
dataSource: DataSource.V20,
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
instrument: 'AUD_USD_CFD',
|
|
77
|
+
displayName: 'AUD/USD CFD',
|
|
78
|
+
dataSource: DataSource.Mt5,
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
const result = groupNamesBySource(items);
|
|
83
|
+
|
|
84
|
+
expect(result).toEqual({
|
|
85
|
+
v20instruments: ['EUR_USD', 'USD_JPY'],
|
|
86
|
+
mt5instruments: ['GBP_USD_CFD', 'AUD_USD_CFD'],
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('should ignore items with unknown data source', () => {
|
|
91
|
+
const items = [
|
|
92
|
+
{
|
|
93
|
+
instrument: 'EUR_USD',
|
|
94
|
+
displayName: 'EUR/USD',
|
|
95
|
+
dataSource: DataSource.V20,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
instrument: 'UNKNOWN_INSTRUMENT',
|
|
99
|
+
displayName: 'Unknown Instrument',
|
|
100
|
+
dataSource: 'UNKNOWN_SOURCE' as any,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
instrument: 'GBP_USD_CFD',
|
|
104
|
+
displayName: 'GBP/USD CFD',
|
|
105
|
+
dataSource: DataSource.Mt5,
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
const result = groupNamesBySource(items);
|
|
110
|
+
|
|
111
|
+
expect(result).toEqual({
|
|
112
|
+
v20instruments: ['EUR_USD'],
|
|
113
|
+
mt5instruments: ['GBP_USD_CFD'],
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should ignore items with undefined data source', () => {
|
|
118
|
+
const items = [
|
|
119
|
+
{
|
|
120
|
+
instrument: 'EUR_USD',
|
|
121
|
+
displayName: 'EUR/USD',
|
|
122
|
+
dataSource: DataSource.V20,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
instrument: 'UNDEFINED_INSTRUMENT',
|
|
126
|
+
displayName: 'Undefined Instrument',
|
|
127
|
+
dataSource: undefined as any,
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
instrument: 'GBP_USD_CFD',
|
|
131
|
+
displayName: 'GBP/USD CFD',
|
|
132
|
+
dataSource: DataSource.Mt5,
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
const result = groupNamesBySource(items);
|
|
137
|
+
|
|
138
|
+
expect(result).toEqual({
|
|
139
|
+
v20instruments: ['EUR_USD'],
|
|
140
|
+
mt5instruments: ['GBP_USD_CFD'],
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should handle items with missing dataSource property', () => {
|
|
145
|
+
const items = [
|
|
146
|
+
{
|
|
147
|
+
instrument: 'EUR_USD',
|
|
148
|
+
displayName: 'EUR/USD',
|
|
149
|
+
dataSource: DataSource.V20,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
instrument: 'MISSING_SOURCE_INSTRUMENT',
|
|
153
|
+
displayName: 'Missing Source Instrument',
|
|
154
|
+
// dataSource property is missing
|
|
155
|
+
} as any,
|
|
156
|
+
{
|
|
157
|
+
instrument: 'GBP_USD_CFD',
|
|
158
|
+
displayName: 'GBP/USD CFD',
|
|
159
|
+
dataSource: DataSource.Mt5,
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
const result = groupNamesBySource(items);
|
|
164
|
+
|
|
165
|
+
expect(result).toEqual({
|
|
166
|
+
v20instruments: ['EUR_USD'],
|
|
167
|
+
mt5instruments: ['GBP_USD_CFD'],
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should preserve order of instruments within each source group', () => {
|
|
172
|
+
const items = [
|
|
173
|
+
{
|
|
174
|
+
instrument: 'AUD_USD',
|
|
175
|
+
displayName: 'AUD/USD',
|
|
176
|
+
dataSource: DataSource.V20,
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
instrument: 'EUR_USD',
|
|
180
|
+
displayName: 'EUR/USD',
|
|
181
|
+
dataSource: DataSource.V20,
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
instrument: 'GBP_USD',
|
|
185
|
+
displayName: 'GBP/USD',
|
|
186
|
+
dataSource: DataSource.V20,
|
|
187
|
+
},
|
|
188
|
+
];
|
|
189
|
+
|
|
190
|
+
const result = groupNamesBySource(items);
|
|
191
|
+
|
|
192
|
+
expect(result.v20instruments).toEqual(['AUD_USD', 'EUR_USD', 'GBP_USD']);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should handle large arrays efficiently', () => {
|
|
196
|
+
const v20Instruments = Array.from({ length: 100 }, (_, i) => ({
|
|
197
|
+
instrument: `V20_INSTRUMENT_${i}`,
|
|
198
|
+
displayName: `V20 Instrument ${i}`,
|
|
199
|
+
dataSource: DataSource.V20,
|
|
200
|
+
}));
|
|
201
|
+
|
|
202
|
+
const mt5Instruments = Array.from({ length: 100 }, (_, i) => ({
|
|
203
|
+
instrument: `MT5_INSTRUMENT_${i}`,
|
|
204
|
+
displayName: `MT5 Instrument ${i}`,
|
|
205
|
+
dataSource: DataSource.Mt5,
|
|
206
|
+
}));
|
|
207
|
+
|
|
208
|
+
const items = [...v20Instruments, ...mt5Instruments];
|
|
209
|
+
|
|
210
|
+
const result = groupNamesBySource(items);
|
|
211
|
+
|
|
212
|
+
expect(result.v20instruments).toHaveLength(100);
|
|
213
|
+
expect(result.mt5instruments).toHaveLength(100);
|
|
214
|
+
expect(result.v20instruments[0]).toBe('V20_INSTRUMENT_0');
|
|
215
|
+
expect(result.mt5instruments[0]).toBe('MT5_INSTRUMENT_0');
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('should handle items with only V20 data source', () => {
|
|
219
|
+
const items = [
|
|
220
|
+
{
|
|
221
|
+
instrument: 'EUR_USD',
|
|
222
|
+
displayName: 'EUR/USD',
|
|
223
|
+
dataSource: DataSource.V20,
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
instrument: 'GBP_USD',
|
|
227
|
+
displayName: 'GBP/USD',
|
|
228
|
+
dataSource: DataSource.V20,
|
|
229
|
+
},
|
|
230
|
+
];
|
|
231
|
+
|
|
232
|
+
const result = groupNamesBySource(items);
|
|
233
|
+
|
|
234
|
+
expect(result.v20instruments).toEqual(['EUR_USD', 'GBP_USD']);
|
|
235
|
+
expect(result.mt5instruments).toEqual([]);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('should handle items with only MT5 data source', () => {
|
|
239
|
+
const items = [
|
|
240
|
+
{
|
|
241
|
+
instrument: 'EUR_USD_CFD',
|
|
242
|
+
displayName: 'EUR/USD CFD',
|
|
243
|
+
dataSource: DataSource.Mt5,
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
instrument: 'GBP_USD_CFD',
|
|
247
|
+
displayName: 'GBP/USD CFD',
|
|
248
|
+
dataSource: DataSource.Mt5,
|
|
249
|
+
},
|
|
250
|
+
];
|
|
251
|
+
|
|
252
|
+
const result = groupNamesBySource(items);
|
|
253
|
+
|
|
254
|
+
expect(result.v20instruments).toEqual([]);
|
|
255
|
+
expect(result.mt5instruments).toEqual(['EUR_USD_CFD', 'GBP_USD_CFD']);
|
|
31
256
|
});
|
|
32
257
|
});
|