Market Data Service is a high-performance financial data API that provides comprehensive Symbol prices of different markets through both RESTful endpoints and real-time WebSocket connections.

candleController.test.js 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. const request = require('supertest');
  2. const app = require('../src/app');
  3. const { Candle, Symbol, sequelize } = require('../src/models');
  4. describe('Candle Controller Integration Tests', () => {
  5. let testSymbol;
  6. beforeAll(async () => {
  7. // Sync database and cleanup
  8. await sequelize.sync({ force: true });
  9. // Create fresh test symbol
  10. testSymbol = await Symbol.create({
  11. symbol: 'TEST_SYMBOL',
  12. exchange: 'TEST',
  13. instrumentType: 'forex'
  14. });
  15. });
  16. afterAll(async () => {
  17. // Cleanup test data
  18. await Candle.destroy({ where: {} });
  19. await Symbol.destroy({ where: {} });
  20. await sequelize.close();
  21. });
  22. describe('POST /api/candles/bulk', () => {
  23. it('should create multiple candles from MT5 payload', async () => {
  24. const mockCandles = [
  25. {
  26. symbolId: testSymbol.id,
  27. timeframe: '1h',
  28. openTime: '2025-10-17T00:00:00.000Z',
  29. closeTime: '2025-10-17T01:00:00.000Z',
  30. open: 1.1000,
  31. high: 1.1050,
  32. low: 1.0990,
  33. close: 1.1025,
  34. volume: 1000
  35. },
  36. {
  37. symbolId: testSymbol.id,
  38. timeframe: '1h',
  39. openTime: '2025-10-17T01:00:00.000Z',
  40. closeTime: '2025-10-17T02:00:00.000Z',
  41. open: 1.1025,
  42. high: 1.1075,
  43. low: 1.1005,
  44. close: 1.1060,
  45. volume: 1200
  46. }
  47. ];
  48. const response = await request(app)
  49. .post('/api/candles/bulk')
  50. .send({ candles: mockCandles })
  51. .expect(201);
  52. expect(response.body.success).toBe(true);
  53. expect(response.body.message).toBe('2 candles created successfully');
  54. expect(response.body.data.length).toBe(2);
  55. // Verify database persistence
  56. const dbCandles = await Candle.findAll({
  57. where: { symbolId: testSymbol.id, timeframe: '1h' },
  58. order: [['openTime', 'ASC']]
  59. });
  60. expect(dbCandles.length).toBe(2);
  61. expect(Number(dbCandles[0].open)).toBeCloseTo(1.1000);
  62. expect(Number(dbCandles[1].close)).toBeCloseTo(1.1060);
  63. });
  64. it('should reject invalid payload format', async () => {
  65. const response = await request(app)
  66. .post('/api/candles/bulk')
  67. .send({ invalid: 'payload' })
  68. .expect(400);
  69. expect(response.body.success).toBe(false);
  70. expect(response.body.message).toContain('Validation error');
  71. });
  72. it('should handle invalid symbol IDs', async () => {
  73. const invalidCandles = [{
  74. symbolId: 999,
  75. timeframe: '1h',
  76. openTime: '2025-10-17T00:00:00.000Z',
  77. closeTime: '2025-10-17T01:00:00.000Z',
  78. open: 1.1000,
  79. high: 1.1050,
  80. low: 1.0990,
  81. close: 1.1025,
  82. volume: 1000
  83. }];
  84. const response = await request(app)
  85. .post('/api/candles/bulk')
  86. .send({ candles: invalidCandles })
  87. .expect(400);
  88. expect(response.body.success).toBe(false);
  89. expect(response.body.message).toContain('Invalid symbol IDs');
  90. });
  91. });
  92. });