Forgot to lint again
Some checks failed
CI/CD Pipeline - Build, Test, and Deploy / 🧪 Test & Lint (push) Successful in 9m31s
CI/CD Pipeline - Build, Test, and Deploy / 🔒 Security Scan (push) Successful in 9m29s
CI/CD Pipeline - Build, Test, and Deploy / 🏗️ Build & Push Image (push) Failing after 11m19s
CI/CD Pipeline - Build, Test, and Deploy / 🛡️ Image Security Scan (push) Has been skipped
CI/CD Pipeline - Build, Test, and Deploy / 🚀 Deploy to Development (push) Has been skipped
CI/CD Pipeline - Build, Test, and Deploy / 🏭 Deploy to Production (push) Has been skipped
CI/CD Pipeline - Build, Test, and Deploy / 🧹 Cleanup (push) Successful in 1s
Some checks failed
CI/CD Pipeline - Build, Test, and Deploy / 🧪 Test & Lint (push) Successful in 9m31s
CI/CD Pipeline - Build, Test, and Deploy / 🔒 Security Scan (push) Successful in 9m29s
CI/CD Pipeline - Build, Test, and Deploy / 🏗️ Build & Push Image (push) Failing after 11m19s
CI/CD Pipeline - Build, Test, and Deploy / 🛡️ Image Security Scan (push) Has been skipped
CI/CD Pipeline - Build, Test, and Deploy / 🚀 Deploy to Development (push) Has been skipped
CI/CD Pipeline - Build, Test, and Deploy / 🏭 Deploy to Production (push) Has been skipped
CI/CD Pipeline - Build, Test, and Deploy / 🧹 Cleanup (push) Successful in 1s
This commit is contained in:
87
tests/api.test.js
Normal file
87
tests/api.test.js
Normal file
@ -0,0 +1,87 @@
|
||||
const request = require('supertest');
|
||||
const app = require('../src/app');
|
||||
|
||||
describe('API Endpoints', () => {
|
||||
describe('GET /api/system', () => {
|
||||
it('should return system information', async() => {
|
||||
const response = await request(app)
|
||||
.get('/api/system')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data).toHaveProperty('hostname');
|
||||
expect(response.body.data).toHaveProperty('platform');
|
||||
expect(response.body.data).toHaveProperty('cpus');
|
||||
expect(response.body.data).toHaveProperty('totalMemory');
|
||||
expect(typeof response.body.data.cpus).toBe('number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /api/memory', () => {
|
||||
it('should return memory information', async() => {
|
||||
const response = await request(app)
|
||||
.get('/api/memory')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data).toHaveProperty('system');
|
||||
expect(response.body.data).toHaveProperty('process');
|
||||
expect(response.body.data.system).toHaveProperty('total');
|
||||
expect(response.body.data.system).toHaveProperty('used');
|
||||
expect(response.body.data.process).toHaveProperty('rss');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /api/process', () => {
|
||||
it('should return process information', async() => {
|
||||
const response = await request(app)
|
||||
.get('/api/process')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data).toHaveProperty('pid');
|
||||
expect(response.body.data).toHaveProperty('uptime');
|
||||
expect(response.body.data).toHaveProperty('version');
|
||||
expect(typeof response.body.data.pid).toBe('number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /api/metrics', () => {
|
||||
it('should return application metrics', async() => {
|
||||
const response = await request(app)
|
||||
.get('/api/metrics')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.data).toHaveProperty('counters');
|
||||
expect(response.body.data).toHaveProperty('gauges');
|
||||
expect(response.body.data).toHaveProperty('histograms');
|
||||
expect(response.body.data).toHaveProperty('runtime');
|
||||
expect(Array.isArray(response.body.data.counters)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /api/test', () => {
|
||||
it('should return test response', async() => {
|
||||
const response = await request(app)
|
||||
.get('/api/test')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body.success).toBe(true);
|
||||
expect(response.body.message).toBe('API is working correctly');
|
||||
expect(response.body).toHaveProperty('version');
|
||||
expect(response.body).toHaveProperty('timestamp');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error handling', () => {
|
||||
it('should return 404 for unknown API endpoints', async() => {
|
||||
const response = await request(app)
|
||||
.get('/api/nonexistent')
|
||||
.expect(404);
|
||||
|
||||
expect(response.body).toHaveProperty('error');
|
||||
expect(response.body.error).toBe('Not Found');
|
||||
});
|
||||
});
|
||||
});
|
||||
93
tests/app.test.js
Normal file
93
tests/app.test.js
Normal file
@ -0,0 +1,93 @@
|
||||
const request = require('supertest');
|
||||
const app = require('../src/app');
|
||||
|
||||
describe('Main Application', () => {
|
||||
describe('Static file serving', () => {
|
||||
it('should serve the main dashboard page', async() => {
|
||||
const response = await request(app)
|
||||
.get('/')
|
||||
.expect(200);
|
||||
|
||||
expect(response.headers['content-type']).toMatch(/html/);
|
||||
});
|
||||
|
||||
it('should serve static CSS files', async() => {
|
||||
const response = await request(app)
|
||||
.get('/style.css')
|
||||
.expect(200);
|
||||
|
||||
expect(response.headers['content-type']).toMatch(/css/);
|
||||
});
|
||||
|
||||
it('should serve static JavaScript files', async() => {
|
||||
const response = await request(app)
|
||||
.get('/app.js')
|
||||
.expect(200);
|
||||
|
||||
expect(response.headers['content-type']).toMatch(/javascript/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Debug endpoints', () => {
|
||||
it('should return debug file information', async() => {
|
||||
const response = await request(app)
|
||||
.get('/debug/files')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body).toHaveProperty('publicPath');
|
||||
expect(response.body).toHaveProperty('files');
|
||||
expect(Array.isArray(response.body.files)).toBe(true);
|
||||
});
|
||||
|
||||
it('should serve test static page', async() => {
|
||||
const response = await request(app)
|
||||
.get('/test-static')
|
||||
.expect(200);
|
||||
|
||||
expect(response.text).toContain('Static File Test');
|
||||
expect(response.headers['content-type']).toMatch(/html/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error handling', () => {
|
||||
it('should return 404 for unknown routes', async() => {
|
||||
const response = await request(app)
|
||||
.get('/nonexistent-route')
|
||||
.expect(404);
|
||||
|
||||
expect(response.body).toHaveProperty('error', 'Not Found');
|
||||
expect(response.body).toHaveProperty('url', '/nonexistent-route');
|
||||
});
|
||||
});
|
||||
|
||||
describe('CORS and Security', () => {
|
||||
it('should include CORS headers', async() => {
|
||||
const response = await request(app)
|
||||
.get('/api/system')
|
||||
.expect(200);
|
||||
|
||||
expect(response.headers).toHaveProperty('access-control-allow-origin');
|
||||
});
|
||||
|
||||
it('should include basic Express headers', async() => {
|
||||
const response = await request(app)
|
||||
.get('/')
|
||||
.expect(200);
|
||||
|
||||
// Check for basic Express headers that should be present
|
||||
expect(response.headers).toHaveProperty('x-powered-by', 'Express');
|
||||
expect(response.headers).toHaveProperty('content-type');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Request logging', () => {
|
||||
it('should log requests without errors', async() => {
|
||||
// This test ensures the logging middleware doesn't crash
|
||||
const response = await request(app)
|
||||
.get('/health')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body).toHaveProperty('status', 'healthy');
|
||||
});
|
||||
});
|
||||
});
|
||||
103
tests/health.test.js
Normal file
103
tests/health.test.js
Normal file
@ -0,0 +1,103 @@
|
||||
const request = require('supertest');
|
||||
const app = require('../src/app');
|
||||
|
||||
describe('Health Check Endpoints', () => {
|
||||
describe('GET /health', () => {
|
||||
it('should return basic health status', async() => {
|
||||
const response = await request(app)
|
||||
.get('/health')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body).toHaveProperty('status', 'healthy');
|
||||
expect(response.body).toHaveProperty('timestamp');
|
||||
expect(response.body).toHaveProperty('uptime');
|
||||
expect(response.body).toHaveProperty('service', 'harbor-ci-cd-demo');
|
||||
expect(typeof response.body.uptime).toBe('number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /health/detailed', () => {
|
||||
it('should return detailed health information', async() => {
|
||||
const response = await request(app)
|
||||
.get('/health/detailed')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body).toHaveProperty('status');
|
||||
expect(response.body).toHaveProperty('timestamp');
|
||||
expect(response.body).toHaveProperty('service', 'harbor-ci-cd-demo');
|
||||
expect(response.body).toHaveProperty('uptime');
|
||||
expect(response.body).toHaveProperty('memory');
|
||||
expect(response.body).toHaveProperty('loadAverage');
|
||||
expect(response.body).toHaveProperty('environment');
|
||||
|
||||
// Check memory structure
|
||||
expect(response.body.memory).toHaveProperty('status');
|
||||
expect(response.body.memory).toHaveProperty('system');
|
||||
expect(response.body.memory).toHaveProperty('process');
|
||||
expect(response.body.memory.system).toHaveProperty('total');
|
||||
expect(response.body.memory.system).toHaveProperty('used');
|
||||
expect(response.body.memory.system).toHaveProperty('percentage');
|
||||
|
||||
// Check uptime structure
|
||||
expect(response.body.uptime).toHaveProperty('process');
|
||||
expect(response.body.uptime).toHaveProperty('system');
|
||||
expect(typeof response.body.uptime.process).toBe('number');
|
||||
expect(typeof response.body.uptime.system).toBe('number');
|
||||
|
||||
// Check load average
|
||||
expect(Array.isArray(response.body.loadAverage)).toBe(true);
|
||||
expect(response.body.loadAverage).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('should include version information', async() => {
|
||||
const response = await request(app)
|
||||
.get('/health/detailed')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body).toHaveProperty('version');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /health/ready', () => {
|
||||
it('should return readiness status', async() => {
|
||||
const response = await request(app)
|
||||
.get('/health/ready')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body).toHaveProperty('status', 'ready');
|
||||
expect(response.body).toHaveProperty('timestamp');
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /health/live', () => {
|
||||
it('should return liveness status', async() => {
|
||||
const response = await request(app)
|
||||
.get('/health/live')
|
||||
.expect(200);
|
||||
|
||||
expect(response.body).toHaveProperty('status', 'alive');
|
||||
expect(response.body).toHaveProperty('timestamp');
|
||||
expect(response.body).toHaveProperty('uptime');
|
||||
expect(typeof response.body.uptime).toBe('number');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Health status validation', () => {
|
||||
it('should return valid timestamp format', async() => {
|
||||
const response = await request(app)
|
||||
.get('/health')
|
||||
.expect(200);
|
||||
|
||||
const timestamp = new Date(response.body.timestamp);
|
||||
expect(timestamp).toBeInstanceOf(Date);
|
||||
expect(timestamp.getTime()).not.toBeNaN();
|
||||
});
|
||||
|
||||
it('should return consistent service name across endpoints', async() => {
|
||||
const basicHealth = await request(app).get('/health');
|
||||
const detailedHealth = await request(app).get('/health/detailed');
|
||||
|
||||
expect(basicHealth.body.service).toBe(detailedHealth.body.service);
|
||||
});
|
||||
});
|
||||
});
|
||||
121
tests/metrics.test.js
Normal file
121
tests/metrics.test.js
Normal file
@ -0,0 +1,121 @@
|
||||
const {
|
||||
incrementCounter,
|
||||
setGauge,
|
||||
recordHistogram,
|
||||
getMetrics,
|
||||
resetMetrics
|
||||
} = require('../src/utils/metrics');
|
||||
|
||||
describe('Metrics Utility', () => {
|
||||
beforeEach(() => {
|
||||
resetMetrics();
|
||||
});
|
||||
|
||||
describe('incrementCounter', () => {
|
||||
it('should increment a counter', () => {
|
||||
incrementCounter('test_counter');
|
||||
incrementCounter('test_counter');
|
||||
|
||||
const metrics = getMetrics();
|
||||
const counter = metrics.counters.find(c => c.name === 'test_counter');
|
||||
|
||||
expect(counter).toBeDefined();
|
||||
expect(counter.value).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle counters with labels', () => {
|
||||
incrementCounter('http_requests', { method: 'GET' });
|
||||
incrementCounter('http_requests', { method: 'POST' });
|
||||
incrementCounter('http_requests', { method: 'GET' });
|
||||
|
||||
const metrics = getMetrics();
|
||||
const getCounter = metrics.counters.find(c =>
|
||||
c.name === 'http_requests' && c.labels.method === 'GET'
|
||||
);
|
||||
const postCounter = metrics.counters.find(c =>
|
||||
c.name === 'http_requests' && c.labels.method === 'POST'
|
||||
);
|
||||
|
||||
expect(getCounter.value).toBe(2);
|
||||
expect(postCounter.value).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setGauge', () => {
|
||||
it('should set a gauge value', () => {
|
||||
setGauge('memory_usage', 85.5);
|
||||
|
||||
const metrics = getMetrics();
|
||||
const gauge = metrics.gauges.find(g => g.name === 'memory_usage');
|
||||
|
||||
expect(gauge).toBeDefined();
|
||||
expect(gauge.value).toBe(85.5);
|
||||
});
|
||||
|
||||
it('should update existing gauge values', () => {
|
||||
setGauge('cpu_usage', 50);
|
||||
setGauge('cpu_usage', 75);
|
||||
|
||||
const metrics = getMetrics();
|
||||
const gauge = metrics.gauges.find(g => g.name === 'cpu_usage');
|
||||
|
||||
expect(gauge.value).toBe(75);
|
||||
});
|
||||
});
|
||||
|
||||
describe('recordHistogram', () => {
|
||||
it('should record histogram values', () => {
|
||||
recordHistogram('response_time', 100);
|
||||
recordHistogram('response_time', 150);
|
||||
recordHistogram('response_time', 200);
|
||||
|
||||
const metrics = getMetrics();
|
||||
const histogram = metrics.histograms.find(h => h.name === 'response_time');
|
||||
|
||||
expect(histogram).toBeDefined();
|
||||
expect(histogram.count).toBe(3);
|
||||
expect(histogram.sum).toBe(450);
|
||||
expect(histogram.average).toBe(150);
|
||||
expect(histogram.min).toBe(100);
|
||||
expect(histogram.max).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMetrics', () => {
|
||||
it('should return all metrics with runtime info', () => {
|
||||
incrementCounter('test_counter');
|
||||
setGauge('test_gauge', 42);
|
||||
recordHistogram('test_histogram', 100);
|
||||
|
||||
const metrics = getMetrics();
|
||||
|
||||
expect(metrics).toHaveProperty('counters');
|
||||
expect(metrics).toHaveProperty('gauges');
|
||||
expect(metrics).toHaveProperty('histograms');
|
||||
expect(metrics).toHaveProperty('runtime');
|
||||
expect(metrics).toHaveProperty('timestamp');
|
||||
|
||||
expect(metrics.counters).toHaveLength(1);
|
||||
expect(metrics.gauges).toHaveLength(1);
|
||||
expect(metrics.histograms).toHaveLength(1);
|
||||
|
||||
expect(metrics.runtime).toHaveProperty('uptime_seconds');
|
||||
expect(metrics.runtime).toHaveProperty('memory_usage_bytes');
|
||||
});
|
||||
});
|
||||
|
||||
describe('resetMetrics', () => {
|
||||
it('should clear all metrics', () => {
|
||||
incrementCounter('test_counter');
|
||||
setGauge('test_gauge', 42);
|
||||
recordHistogram('test_histogram', 100);
|
||||
|
||||
resetMetrics();
|
||||
|
||||
const metrics = getMetrics();
|
||||
expect(metrics.counters).toHaveLength(0);
|
||||
expect(metrics.gauges).toHaveLength(0);
|
||||
expect(metrics.histograms).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user