Merge pull request #103 from tiagosiebler/#3/tests
feat(#3): add initial integration tests for public api calls
This commit is contained in:
31
.circleci/config.yml
Normal file
31
.circleci/config.yml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
version: 2.1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
docker:
|
||||||
|
- image: cimg/node:15.1
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- restore_cache:
|
||||||
|
# See the configuration reference documentation for more details on using restore_cache and save_cache steps
|
||||||
|
# https://circleci.com/docs/2.0/configuration-reference/?section=reference#save_cache
|
||||||
|
keys:
|
||||||
|
- node-deps-v1-{{ .Branch }}-{{checksum "package-lock.json"}}
|
||||||
|
- run:
|
||||||
|
name: install packages
|
||||||
|
command: npm ci
|
||||||
|
- save_cache:
|
||||||
|
key: node-deps-v1-{{ .Branch }}-{{checksum "package-lock.json"}}
|
||||||
|
paths:
|
||||||
|
- ~/.npm
|
||||||
|
- run:
|
||||||
|
name: Run Build
|
||||||
|
command: npm run build
|
||||||
|
- run:
|
||||||
|
name: Run Tests
|
||||||
|
command: npm run test
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
integrationtests:
|
||||||
|
jobs:
|
||||||
|
- test
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
# bybit-api
|
# bybit-api
|
||||||
|
[](https://circleci.com/gh/tiagosiebler/bybit-api)
|
||||||
[][1] [][1] [][1]
|
[][1] [][1] [][1]
|
||||||
[][1]
|
[][1]
|
||||||
[](https://www.codefactor.io/repository/github/tiagosiebler/bybit-api)
|
[](https://www.codefactor.io/repository/github/tiagosiebler/bybit-api)
|
||||||
|
|||||||
28
jest.config.js
Normal file
28
jest.config.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// jest.config.js
|
||||||
|
module.exports = {
|
||||||
|
rootDir: './',
|
||||||
|
globals: {
|
||||||
|
__DEV__: true,
|
||||||
|
__PROD__: false
|
||||||
|
},
|
||||||
|
testEnvironment: 'node',
|
||||||
|
preset: "ts-jest",
|
||||||
|
verbose: true, // report individual test
|
||||||
|
bail: false, // enable to stop test when an error occur,
|
||||||
|
detectOpenHandles: false,
|
||||||
|
moduleDirectories: ['node_modules', 'src', 'test'],
|
||||||
|
testMatch: ['**/test/**/*.test.ts?(x)'],
|
||||||
|
testPathIgnorePatterns: ['node_modules/', 'dist/', '.json'],
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'src/**/*.ts'
|
||||||
|
],
|
||||||
|
coverageThreshold: {
|
||||||
|
// coverage strategy
|
||||||
|
global: {
|
||||||
|
branches: 80,
|
||||||
|
functions: 80,
|
||||||
|
lines: 50,
|
||||||
|
statements: -10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
3795
package-lock.json
generated
3795
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,8 @@
|
|||||||
"index.js"
|
"index.js"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "jest",
|
||||||
|
"test:watch": "jest --watch",
|
||||||
"clean": "rm -rf lib dist",
|
"clean": "rm -rf lib dist",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"build:clean": "npm run clean && npm run build",
|
"build:clean": "npm run clean && npm run build",
|
||||||
@@ -28,9 +29,12 @@
|
|||||||
"ws": "^7.4.0"
|
"ws": "^7.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/jest": "^26.0.23",
|
||||||
"@types/node": "^14.14.7",
|
"@types/node": "^14.14.7",
|
||||||
"eslint": "^7.10.0",
|
"eslint": "^7.10.0",
|
||||||
|
"jest": "^27.0.4",
|
||||||
"source-map-loader": "^2.0.0",
|
"source-map-loader": "^2.0.0",
|
||||||
|
"ts-jest": "^27.0.3",
|
||||||
"ts-loader": "^8.0.11",
|
"ts-loader": "^8.0.11",
|
||||||
"typescript": "^4.0.5",
|
"typescript": "^4.0.5",
|
||||||
"webpack": "^5.4.0",
|
"webpack": "^5.4.0",
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ export class InverseClient extends SharedEndpoints {
|
|||||||
restClientOptions: RestClientOptions = {},
|
restClientOptions: RestClientOptions = {},
|
||||||
requestOptions: AxiosRequestConfig = {}
|
requestOptions: AxiosRequestConfig = {}
|
||||||
) {
|
) {
|
||||||
super()
|
super();
|
||||||
|
|
||||||
this.requestWrapper = new RequestWrapper(
|
this.requestWrapper = new RequestWrapper(
|
||||||
key,
|
key,
|
||||||
secret,
|
secret,
|
||||||
@@ -53,9 +54,9 @@ export class InverseClient extends SharedEndpoints {
|
|||||||
*/
|
*/
|
||||||
getLatestInformation(params?: {
|
getLatestInformation(params?: {
|
||||||
symbol?: string;
|
symbol?: string;
|
||||||
}): GenericAPIResponse {
|
}): GenericAPIResponse {
|
||||||
return this.getTickers(params);
|
return this.getTickers(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use getTrades() instead
|
* @deprecated use getTrades() instead
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ export class InverseFuturesClient extends SharedEndpoints {
|
|||||||
restClientOptions: RestClientOptions = {},
|
restClientOptions: RestClientOptions = {},
|
||||||
requestOptions: AxiosRequestConfig = {}
|
requestOptions: AxiosRequestConfig = {}
|
||||||
) {
|
) {
|
||||||
super()
|
super();
|
||||||
|
|
||||||
this.requestWrapper = new RequestWrapper(
|
this.requestWrapper = new RequestWrapper(
|
||||||
key,
|
key,
|
||||||
secret,
|
secret,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export class LinearClient extends SharedEndpoints {
|
|||||||
protected requestWrapper: RequestWrapper;
|
protected requestWrapper: RequestWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public Creates an instance of the inverse REST API client.
|
* @public Creates an instance of the linear REST API client.
|
||||||
*
|
*
|
||||||
* @param {string} key - your API key
|
* @param {string} key - your API key
|
||||||
* @param {string} secret - your API secret
|
* @param {string} secret - your API secret
|
||||||
@@ -22,7 +22,8 @@ export class LinearClient extends SharedEndpoints {
|
|||||||
restClientOptions: RestClientOptions = {},
|
restClientOptions: RestClientOptions = {},
|
||||||
requestOptions: AxiosRequestConfig = {}
|
requestOptions: AxiosRequestConfig = {}
|
||||||
) {
|
) {
|
||||||
super()
|
super();
|
||||||
|
|
||||||
this.requestWrapper = new RequestWrapper(
|
this.requestWrapper = new RequestWrapper(
|
||||||
key,
|
key,
|
||||||
secret,
|
secret,
|
||||||
|
|||||||
70
test/inverse-futures/public.test.ts
Normal file
70
test/inverse-futures/public.test.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import { InverseFuturesClient } from "../../src/inverse-futures-client";
|
||||||
|
import { notAuthenticatedError, successResponseList, successResponseObject } from "../response.util";
|
||||||
|
|
||||||
|
describe('Public Inverse Futures REST API Endpoints', () => {
|
||||||
|
const useLivenet = true;
|
||||||
|
const api = new InverseFuturesClient(undefined, undefined, useLivenet, { disable_time_sync: true });
|
||||||
|
|
||||||
|
const symbol = 'BTCUSD';
|
||||||
|
const interval = '15';
|
||||||
|
const timestampOneHourAgo = (new Date().getTime() / 1000) - (1000 * 60 * 60);
|
||||||
|
const from = Number(timestampOneHourAgo.toFixed(0));
|
||||||
|
|
||||||
|
describe('Inverse-Futures only endpoints', () => {
|
||||||
|
it('should throw for unauthenticated private calls', async () => {
|
||||||
|
expect(() => api.getPosition()).rejects.toMatchObject(notAuthenticatedError());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getKline()', async () => {
|
||||||
|
expect(
|
||||||
|
await api.getKline({ symbol, interval, from })
|
||||||
|
).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getTrades()', async () => {
|
||||||
|
expect(await api.getTrades({ symbol })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getIndexPriceKline()', async () => {
|
||||||
|
expect(await api.getIndexPriceKline({ symbol, interval, from })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getPremiumIndexKline()', async () => {
|
||||||
|
expect(await api.getPremiumIndexKline({ symbol, interval, from })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getLastFundingRate()', async () => {
|
||||||
|
expect(await api.getLastFundingRate({ symbol })).toMatchObject(successResponseObject());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Shared endpoints', () => {
|
||||||
|
it('should throw for unauthenticated private calls', async () => {
|
||||||
|
expect(() => api.getApiKeyInfo()).rejects.toMatchObject(notAuthenticatedError());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getOrderBook()', async () => {
|
||||||
|
expect(await api.getOrderBook({ symbol })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getTickers()', async () => {
|
||||||
|
expect(await api.getTickers()).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSymbols()', async () => {
|
||||||
|
expect(await api.getSymbols()).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getLiquidations()', async () => {
|
||||||
|
expect(await api.getLiquidations({ symbol })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getServerTime()', async () => {
|
||||||
|
expect(await api.getServerTime()).toMatchObject(successResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getApiAnnouncements()', async () => {
|
||||||
|
expect(await api.getApiAnnouncements()).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
70
test/inverse/public.test.ts
Normal file
70
test/inverse/public.test.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import { InverseClient } from "../../src/inverse-client";
|
||||||
|
import { notAuthenticatedError, successResponseList, successResponseObject } from "../response.util";
|
||||||
|
|
||||||
|
describe('Public Inverse REST API Endpoints', () => {
|
||||||
|
const useLivenet = true;
|
||||||
|
const api = new InverseClient(undefined, undefined, useLivenet, { disable_time_sync: true });
|
||||||
|
|
||||||
|
const symbol = 'BTCUSD';
|
||||||
|
const interval = '15';
|
||||||
|
const timestampOneHourAgo = (new Date().getTime() / 1000) - (1000 * 60 * 60);
|
||||||
|
const from = Number(timestampOneHourAgo.toFixed(0));
|
||||||
|
|
||||||
|
describe('Inverse only endpoints', () => {
|
||||||
|
it('should throw for unauthenticated private calls', async () => {
|
||||||
|
expect(() => api.getPosition()).rejects.toMatchObject(notAuthenticatedError());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getKline()', async () => {
|
||||||
|
expect(
|
||||||
|
await api.getKline({ symbol, interval, from })
|
||||||
|
).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getTrades()', async () => {
|
||||||
|
expect(await api.getTrades({ symbol })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getIndexPriceKline()', async () => {
|
||||||
|
expect(await api.getIndexPriceKline({ symbol, interval, from })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getPremiumIndexKline()', async () => {
|
||||||
|
expect(await api.getPremiumIndexKline({ symbol, interval, from })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getLastFundingRate()', async () => {
|
||||||
|
expect(await api.getLastFundingRate({ symbol })).toMatchObject(successResponseObject());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Shared endpoints', () => {
|
||||||
|
it('should throw for unauthenticated private calls', async () => {
|
||||||
|
expect(() => api.getApiKeyInfo()).rejects.toMatchObject(notAuthenticatedError());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getOrderBook()', async () => {
|
||||||
|
expect(await api.getOrderBook({ symbol })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getTickers()', async () => {
|
||||||
|
expect(await api.getTickers()).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSymbols()', async () => {
|
||||||
|
expect(await api.getSymbols()).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getLiquidations()', async () => {
|
||||||
|
expect(await api.getLiquidations({ symbol })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getServerTime()', async () => {
|
||||||
|
expect(await api.getServerTime()).toMatchObject(successResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getApiAnnouncements()', async () => {
|
||||||
|
expect(await api.getApiAnnouncements()).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
70
test/linear/public.test.ts
Normal file
70
test/linear/public.test.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import { LinearClient } from "../../src/linear-client";
|
||||||
|
import { notAuthenticatedError, successResponseList, successResponseObject } from "../response.util";
|
||||||
|
|
||||||
|
describe('Public Linear REST API Endpoints', () => {
|
||||||
|
const useLivenet = true;
|
||||||
|
const api = new LinearClient(undefined, undefined, useLivenet, { disable_time_sync: true });
|
||||||
|
|
||||||
|
const symbol = 'BTCUSDT';
|
||||||
|
const interval = '15';
|
||||||
|
const timestampOneHourAgo = (new Date().getTime() / 1000) - (1000 * 60 * 60);
|
||||||
|
const from = Number(timestampOneHourAgo.toFixed(0));
|
||||||
|
|
||||||
|
describe('Linear only endpoints', () => {
|
||||||
|
it('should throw for unauthenticated private calls', async () => {
|
||||||
|
expect(() => api.getPosition()).rejects.toMatchObject(notAuthenticatedError());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getKline()', async () => {
|
||||||
|
expect(
|
||||||
|
await api.getKline({ symbol, interval, from })
|
||||||
|
).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getTrades()', async () => {
|
||||||
|
expect(await api.getTrades({ symbol })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getIndexPriceKline()', async () => {
|
||||||
|
expect(await api.getIndexPriceKline({ symbol, interval, from })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getPremiumIndexKline()', async () => {
|
||||||
|
expect(await api.getPremiumIndexKline({ symbol, interval, from })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getLastFundingRate()', async () => {
|
||||||
|
expect(await api.getLastFundingRate({ symbol })).toMatchObject(successResponseObject());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Shared endpoints', () => {
|
||||||
|
it('should throw for unauthenticated private calls', async () => {
|
||||||
|
expect(() => api.getApiKeyInfo()).rejects.toMatchObject(notAuthenticatedError());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getOrderBook()', async () => {
|
||||||
|
expect(await api.getOrderBook({ symbol })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getTickers()', async () => {
|
||||||
|
expect(await api.getTickers()).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getSymbols()', async () => {
|
||||||
|
expect(await api.getSymbols()).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getLiquidations()', async () => {
|
||||||
|
expect(await api.getLiquidations({ symbol })).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getServerTime()', async () => {
|
||||||
|
expect(await api.getServerTime()).toMatchObject(successResponseObject());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('getApiAnnouncements()', async () => {
|
||||||
|
expect(await api.getApiAnnouncements()).toMatchObject(successResponseList());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
26
test/response.util.ts
Normal file
26
test/response.util.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
export function successResponseList() {
|
||||||
|
return {
|
||||||
|
"ext_code": "",
|
||||||
|
"ext_info": "",
|
||||||
|
"result": expect.any(Array),
|
||||||
|
"ret_code": 0,
|
||||||
|
"ret_msg": "OK",
|
||||||
|
"time_now": expect.any(String),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function successResponseObject() {
|
||||||
|
return {
|
||||||
|
"ext_code": "",
|
||||||
|
"ext_info": "",
|
||||||
|
"result": expect.any(Object),
|
||||||
|
"ret_code": 0,
|
||||||
|
"ret_msg": "OK",
|
||||||
|
"time_now": expect.any(String),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function notAuthenticatedError() {
|
||||||
|
return new Error('Private endpoints require api and private keys set');
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user