| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- const request = require('supertest');
- const { expect } = require('chai');
- const app = require('../src/server');
- const { getHistoricalCandles, validateCandles, generateTestCandles } = require('../services/candlestickService');
- describe('Candlestick API Tests', () => {
- const testSymbol = 'EURUSD';
- const testTimeframe = 'H1';
- describe('GET /api/prices/validate-candles/:symbol', () => {
- it('should validate candles for a valid symbol', async () => {
- const response = await request(app)
- .get(`/api/prices/validate-candles/${testSymbol}`)
- .query({ timeframe: testTimeframe, limit: 50 })
- .expect(200);
- expect(response.body.status).to.equal('success');
- expect(response.body.data).to.have.property('total');
- expect(response.body.data).to.have.property('valid');
- expect(response.body.data).to.have.property('invalid');
- expect(response.body.data.total).to.be.greaterThan(0);
- });
- it('should return 400 for missing symbol', async () => {
- const response = await request(app)
- .get('/api/prices/validate-candles/')
- .expect(404); // Express will return 404 for missing route param
- });
- it('should handle different timeframes', async () => {
- const timeframes = ['M1', 'M5', 'M15', 'H1', 'H4', 'D1'];
- for (const timeframe of timeframes) {
- const response = await request(app)
- .get(`/api/prices/validate-candles/${testSymbol}`)
- .query({ timeframe, limit: 10 })
- .expect(200);
- expect(response.body.status).to.equal('success');
- expect(response.body.timeframe).to.equal(timeframe);
- }
- });
- });
- describe('GET /api/prices/generate-test-candles/:symbol', () => {
- it('should generate test candles for a valid symbol', async () => {
- const response = await request(app)
- .get(`/api/prices/generate-test-candles/${testSymbol}`)
- .query({ timeframe: testTimeframe, count: 20 })
- .expect(200);
- expect(response.body.status).to.equal('success');
- expect(response.body.data).to.be.an('array');
- expect(response.body.data.length).to.equal(20);
- expect(response.body.validation).to.have.property('total', 20);
- });
- it('should validate generated test candles', async () => {
- const response = await request(app)
- .get(`/api/prices/generate-test-candles/${testSymbol}`)
- .query({ timeframe: testTimeframe, count: 10 })
- .expect(200);
- expect(response.body.meta.validationPassed).to.equal(true);
- expect(response.body.meta.successRate).to.equal('100.00%');
- });
- });
- describe('GET /api/prices/candle-info/:symbol', () => {
- it('should return candle statistics for a valid symbol', async () => {
- const response = await request(app)
- .get(`/api/prices/candle-info/${testSymbol}`)
- .query({ timeframe: testTimeframe })
- .expect(200);
- expect(response.body.status).to.equal('success');
- expect(response.body.data).to.have.property('count');
- expect(response.body.data).to.have.property('priceRange');
- expect(response.body.data).to.have.property('volume');
- expect(response.body.data.symbol).to.equal(testSymbol.toUpperCase());
- });
- });
- describe('Candlestick Service Unit Tests', () => {
- it('should generate valid test candles', () => {
- const candles = generateTestCandles(testSymbol, testTimeframe, 10);
- expect(candles).to.have.length(10);
- candles.forEach(candle => {
- expect(candle.symbol).to.equal(testSymbol);
- expect(candle.timeframe).to.equal(testTimeframe);
- expect(candle).to.have.property('open');
- expect(candle).to.have.property('high');
- expect(candle).to.have.property('low');
- expect(candle).to.have.property('close');
- expect(candle).to.have.property('volume');
- expect(candle).to.have.property('timestamp');
- });
- });
- it('should validate correct candles', () => {
- const validCandles = generateTestCandles(testSymbol, testTimeframe, 5);
- const results = validateCandles(validCandles);
- expect(results.total).to.equal(5);
- expect(results.valid).to.equal(5);
- expect(results.invalid).to.equal(0);
- expect(results.issues).to.have.length(0);
- });
- it('should detect invalid candles', () => {
- const invalidCandles = [
- {
- symbol: testSymbol,
- timeframe: testTimeframe,
- timestamp: new Date(),
- open: 'invalid',
- high: 1.1,
- low: 1.0,
- close: 1.05,
- volume: 1000
- },
- {
- symbol: testSymbol,
- timeframe: testTimeframe,
- timestamp: new Date(),
- open: 1.0,
- high: 0.9, // Invalid: high < open
- low: 1.0,
- close: 1.05,
- volume: 1000
- }
- ];
- const results = validateCandles(invalidCandles);
- expect(results.invalid).to.be.greaterThan(0);
- expect(results.issues.length).to.be.greaterThan(0);
- });
- });
- describe('GET /api/prices/historical/:symbol (Integration)', () => {
- it('should return historical data that can be validated', async () => {
- const response = await request(app)
- .get(`/api/prices/historical/${testSymbol}`)
- .query({ timeframe: testTimeframe, limit: 20 })
- .expect(200);
- expect(response.body.status).to.equal('success');
- expect(response.body.data).to.be.an('array');
- if (response.body.data.length > 0) {
- // Validate the returned candles
- const validationResults = validateCandles(response.body.data);
- expect(validationResults.total).to.equal(response.body.data.length);
- // Log validation results for debugging
- console.log(`Historical data validation: ${validationResults.valid}/${validationResults.total} valid candles`);
- }
- });
- });
- describe('Chart Data Format Tests', () => {
- it('should return data in correct format for charting', async () => {
- const response = await request(app)
- .get(`/api/prices/historical/${testSymbol}`)
- .query({ timeframe: testTimeframe, limit: 10 })
- .expect(200);
- expect(response.body.status).to.equal('success');
- expect(response.body.data).to.be.an('array');
- if (response.body.data.length > 0) {
- const candle = response.body.data[0];
- // Check required fields for charting
- expect(candle).to.have.property('timestamp');
- expect(candle).to.have.property('open');
- expect(candle).to.have.property('high');
- expect(candle).to.have.property('low');
- expect(candle).to.have.property('close');
- // Validate data types
- expect(typeof candle.open).to.equal('number');
- expect(typeof candle.high).to.equal('number');
- expect(typeof candle.low).to.equal('number');
- expect(typeof candle.close).to.equal('number');
- // Validate price logic
- expect(candle.high).to.be.at.least(Math.max(candle.open, candle.close));
- expect(candle.low).to.be.at.most(Math.min(candle.open, candle.close));
- }
- });
- });
- });
- // Helper function to wait for price updates
- const waitForPriceUpdate = (ms = 2000) => {
- return new Promise(resolve => setTimeout(resolve, ms));
- };
- module.exports = {
- waitForPriceUpdate
- };
|