Skip to content

Commit 2a68fb4

Browse files
committed
add tests
1 parent 49d25a8 commit 2a68fb4

1 file changed

Lines changed: 279 additions & 0 deletions

File tree

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
import Binance from '../src/node-binance-api';
2+
import { assert } from 'chai';
3+
4+
const WARN_SHOULD_BE_OBJ = 'should be an object';
5+
const WARN_SHOULD_BE_NOT_NULL = 'should not be null';
6+
const WARN_SHOULD_HAVE_KEY = 'should have key ';
7+
const WARN_SHOULD_BE_TYPE = 'should be a ';
8+
const TIMEOUT = 30000;
9+
10+
const binance = new Binance().options({
11+
APIKEY: 'X4BHNSimXOK6RKs2FcKqExquJtHjMxz5hWqF0BBeVnfa5bKFMk7X0wtkfEz0cPrJ',
12+
APISECRET: 'x8gLihunpNq0d46F2q0TWJmeCDahX5LMXSlv3lSFNbMI3rujSOpTDKdhbcmPSf2i',
13+
test: true,
14+
verbose: false
15+
});
16+
17+
describe('WebSocket API Ticker Price', function () {
18+
19+
describe('tickerPrice - Single Symbol', function () {
20+
it('should fetch price for a single symbol', async function () {
21+
this.timeout(TIMEOUT);
22+
23+
const result = await binance.tickerPrice('BTCUSDT');
24+
25+
assert(result !== null, WARN_SHOULD_BE_NOT_NULL);
26+
assert(typeof result === 'object', WARN_SHOULD_BE_OBJ);
27+
assert(Object.prototype.hasOwnProperty.call(result, 'symbol'), WARN_SHOULD_HAVE_KEY + 'symbol');
28+
assert(Object.prototype.hasOwnProperty.call(result, 'price'), WARN_SHOULD_HAVE_KEY + 'price');
29+
assert(result.symbol === 'BTCUSDT', 'Symbol should be BTCUSDT');
30+
assert(typeof result.price === 'string', WARN_SHOULD_BE_TYPE + 'string');
31+
assert(parseFloat(result.price) > 0, 'Price should be positive');
32+
33+
console.log('Single symbol result:', result);
34+
});
35+
36+
it('should fetch price for another symbol', async function () {
37+
this.timeout(TIMEOUT);
38+
39+
const result = await binance.tickerPrice('ETHUSDT');
40+
41+
assert(result !== null, WARN_SHOULD_BE_NOT_NULL);
42+
assert(typeof result === 'object', WARN_SHOULD_BE_OBJ);
43+
assert(result.symbol === 'ETHUSDT', 'Symbol should be ETHUSDT');
44+
assert(Object.prototype.hasOwnProperty.call(result, 'price'), WARN_SHOULD_HAVE_KEY + 'price');
45+
assert(parseFloat(result.price) > 0, 'Price should be positive');
46+
47+
console.log('ETHUSDT price:', result.price);
48+
});
49+
});
50+
51+
describe('tickerPrice - Multiple Symbols', function () {
52+
it('should fetch prices for multiple symbols', async function () {
53+
this.timeout(TIMEOUT);
54+
55+
const symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT'];
56+
const result = await binance.tickerPrice(undefined, symbols);
57+
58+
assert(result !== null, WARN_SHOULD_BE_NOT_NULL);
59+
assert(Array.isArray(result), 'Result should be an array');
60+
assert(result.length === symbols.length, `Should return ${symbols.length} prices`);
61+
62+
result.forEach((ticker: any, index: number) => {
63+
assert(typeof ticker === 'object', WARN_SHOULD_BE_OBJ);
64+
assert(Object.prototype.hasOwnProperty.call(ticker, 'symbol'), WARN_SHOULD_HAVE_KEY + 'symbol');
65+
assert(Object.prototype.hasOwnProperty.call(ticker, 'price'), WARN_SHOULD_HAVE_KEY + 'price');
66+
assert(symbols.includes(ticker.symbol), `Symbol ${ticker.symbol} should be in requested list`);
67+
assert(typeof ticker.price === 'string', WARN_SHOULD_BE_TYPE + 'string');
68+
assert(parseFloat(ticker.price) > 0, `Price for ${ticker.symbol} should be positive`);
69+
});
70+
71+
console.log('Multiple symbols result:', result);
72+
});
73+
74+
it('should fetch prices for 5 symbols', async function () {
75+
this.timeout(TIMEOUT);
76+
77+
const symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'ADAUSDT', 'DOGEUSDT'];
78+
const result = await binance.tickerPrice(undefined, symbols);
79+
80+
assert(Array.isArray(result), 'Result should be an array');
81+
assert(result.length === symbols.length, `Should return ${symbols.length} prices`);
82+
83+
const returnedSymbols = result.map((ticker: any) => ticker.symbol);
84+
symbols.forEach(symbol => {
85+
assert(returnedSymbols.includes(symbol), `Should include ${symbol}`);
86+
});
87+
88+
console.log(`Fetched prices for ${result.length} symbols`);
89+
});
90+
});
91+
92+
describe('tickerPrice - All Symbols', function () {
93+
it('should fetch prices for all symbols when no parameters provided', async function () {
94+
this.timeout(TIMEOUT);
95+
96+
const result = await binance.tickerPrice();
97+
98+
assert(result !== null, WARN_SHOULD_BE_NOT_NULL);
99+
assert(Array.isArray(result), 'Result should be an array');
100+
assert(result.length > 0, 'Should return at least one symbol');
101+
102+
// Check first few results
103+
result.slice(0, 5).forEach((ticker: any) => {
104+
assert(typeof ticker === 'object', WARN_SHOULD_BE_OBJ);
105+
assert(Object.prototype.hasOwnProperty.call(ticker, 'symbol'), WARN_SHOULD_HAVE_KEY + 'symbol');
106+
assert(Object.prototype.hasOwnProperty.call(ticker, 'price'), WARN_SHOULD_HAVE_KEY + 'price');
107+
assert(typeof ticker.symbol === 'string', 'Symbol should be string');
108+
assert(typeof ticker.price === 'string', 'Price should be string');
109+
});
110+
111+
console.log(`Fetched prices for ${result.length} total symbols`);
112+
});
113+
});
114+
115+
describe('tickerPrice - With Symbol Status Filter', function () {
116+
it('should filter by TRADING status', async function () {
117+
this.timeout(TIMEOUT);
118+
119+
const result = await binance.tickerPrice('BTCUSDT', undefined, { symbolStatus: 'TRADING' });
120+
121+
assert(result !== null, WARN_SHOULD_BE_NOT_NULL);
122+
assert(typeof result === 'object', WARN_SHOULD_BE_OBJ);
123+
assert(result.symbol === 'BTCUSDT', 'Symbol should be BTCUSDT');
124+
assert(Object.prototype.hasOwnProperty.call(result, 'price'), WARN_SHOULD_HAVE_KEY + 'price');
125+
126+
console.log('Filtered result (TRADING):', result);
127+
});
128+
129+
it('should filter multiple symbols by status', async function () {
130+
this.timeout(TIMEOUT);
131+
132+
const symbols = ['BTCUSDT', 'ETHUSDT'];
133+
const result = await binance.tickerPrice(undefined, symbols, { symbolStatus: 'TRADING' });
134+
135+
assert(Array.isArray(result), 'Result should be an array');
136+
// Result may be filtered, so length could be <= symbols.length
137+
assert(result.length <= symbols.length, 'Result should not exceed requested symbols');
138+
139+
console.log(`Filtered ${result.length} trading symbols from ${symbols.length} requested`);
140+
});
141+
});
142+
143+
describe('tickerPrice - Error Handling', function () {
144+
it('should reject when both symbol and symbols are provided', async function () {
145+
this.timeout(TIMEOUT);
146+
147+
try {
148+
await binance.tickerPrice('BTCUSDT', ['ETHUSDT']);
149+
assert.fail('Should have thrown an error');
150+
} catch (error: any) {
151+
assert(error.message.includes('Cannot specify both'), 'Should indicate parameter conflict');
152+
}
153+
});
154+
155+
it('should handle invalid symbol gracefully', async function () {
156+
this.timeout(TIMEOUT);
157+
158+
try {
159+
await binance.tickerPrice('INVALIDSYMBOL123');
160+
// May succeed or fail depending on Binance's handling
161+
// If it succeeds, it might return an empty result or error in result
162+
} catch (error: any) {
163+
// Expected to fail with invalid symbol
164+
assert(error !== null, 'Should have error information');
165+
}
166+
});
167+
});
168+
169+
describe('tickerPrice - Response Structure', function () {
170+
it('should include rate limit information', async function () {
171+
this.timeout(TIMEOUT);
172+
173+
// Note: Rate limit info is in the JSON-RPC response but may not be returned by our method
174+
// This test documents the expected structure
175+
176+
const result = await binance.tickerPrice('BTCUSDT');
177+
178+
assert(result !== null, WARN_SHOULD_BE_NOT_NULL);
179+
assert(Object.prototype.hasOwnProperty.call(result, 'symbol'), 'Should have symbol');
180+
assert(Object.prototype.hasOwnProperty.call(result, 'price'), 'Should have price');
181+
182+
// Note: rateLimits may be stripped by our implementation
183+
// Full response from API includes: { symbol, price }
184+
});
185+
186+
it('should return consistent structure for single and multiple symbols', async function () {
187+
this.timeout(TIMEOUT);
188+
189+
const singleResult = await binance.tickerPrice('BTCUSDT');
190+
const multiResult = await binance.tickerPrice(undefined, ['BTCUSDT']);
191+
192+
assert(typeof singleResult === 'object', 'Single result should be object');
193+
assert(!Array.isArray(singleResult), 'Single result should not be array');
194+
195+
assert(Array.isArray(multiResult), 'Multi result should be array');
196+
assert(multiResult.length > 0, 'Multi result should have items');
197+
198+
// Compare structure
199+
const multiItem = multiResult[0];
200+
assert(Object.keys(singleResult).length > 0, 'Single result should have keys');
201+
assert(Object.keys(multiItem).length > 0, 'Multi item should have keys');
202+
});
203+
});
204+
205+
describe('tickerPrice - WebSocket API Features', function () {
206+
it('should use WebSocket API connection', async function () {
207+
this.timeout(TIMEOUT);
208+
209+
const startTime = Date.now();
210+
const result = await binance.tickerPrice('BTCUSDT');
211+
const endTime = Date.now();
212+
213+
const responseTime = endTime - startTime;
214+
215+
assert(result !== null, WARN_SHOULD_BE_NOT_NULL);
216+
console.log(`WebSocket API response time: ${responseTime}ms`);
217+
218+
// WebSocket should be reasonably fast
219+
assert(responseTime < 10000, 'Should respond within 10 seconds');
220+
});
221+
222+
it('should handle concurrent requests', async function () {
223+
this.timeout(TIMEOUT);
224+
225+
const promises = [
226+
binance.tickerPrice('BTCUSDT'),
227+
binance.tickerPrice('ETHUSDT'),
228+
binance.tickerPrice('BNBUSDT')
229+
];
230+
231+
const results = await Promise.all(promises);
232+
233+
assert(results.length === 3, 'Should have 3 results');
234+
results.forEach((result, index) => {
235+
assert(result !== null, `Result ${index} should not be null`);
236+
assert(typeof result === 'object', `Result ${index} should be object`);
237+
assert(Object.prototype.hasOwnProperty.call(result, 'price'), `Result ${index} should have price`);
238+
});
239+
240+
console.log('Concurrent requests completed successfully');
241+
});
242+
});
243+
244+
describe('tickerPrice - Price Validation', function () {
245+
it('should return valid numeric price strings', async function () {
246+
this.timeout(TIMEOUT);
247+
248+
const result = await binance.tickerPrice('BTCUSDT');
249+
250+
assert(result !== null, WARN_SHOULD_BE_NOT_NULL);
251+
assert(typeof result.price === 'string', 'Price should be string');
252+
253+
const priceFloat = parseFloat(result.price);
254+
assert(!isNaN(priceFloat), 'Price should be valid number');
255+
assert(isFinite(priceFloat), 'Price should be finite');
256+
assert(priceFloat > 0, 'Price should be positive');
257+
258+
// Check decimal format
259+
assert(/^\d+(\.\d+)?$/.test(result.price), 'Price should match decimal pattern');
260+
261+
console.log(`BTCUSDT price: ${result.price} (${priceFloat})`);
262+
});
263+
264+
it('should return prices with appropriate precision', async function () {
265+
this.timeout(TIMEOUT);
266+
267+
const symbols = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT'];
268+
const results = await binance.tickerPrice(undefined, symbols);
269+
270+
results.forEach((ticker: any) => {
271+
const decimalPlaces = (ticker.price.split('.')[1] || '').length;
272+
assert(decimalPlaces >= 0, `Price for ${ticker.symbol} should have decimal places`);
273+
assert(decimalPlaces <= 8, `Price for ${ticker.symbol} should not exceed 8 decimal places`);
274+
275+
console.log(`${ticker.symbol}: ${ticker.price} (${decimalPlaces} decimals)`);
276+
});
277+
});
278+
});
279+
});

0 commit comments

Comments
 (0)