**Cache-Busting Improvements:** - Switched from timestamp-based to semantic versioning (v1.0.2) - Updated all HTML files: index.html, docs.html, leader.html - CSS: tailwind.css?v=1.0.2 - JS: navbar.js, document-cards.js, docs-app.js v1.0.2 - Professional versioning approach for production stability **systemd Service Implementation:** - Created tractatus-dev.service for development environment - Created tractatus-prod.service for production environment - Added install-systemd.sh script for easy deployment - Security hardening: NoNewPrivileges, PrivateTmp, ProtectSystem - Resource limits: 1GB dev, 2GB prod memory limits - Proper logging integration with journalctl - Automatic restart on failure (RestartSec=10) **Why systemd over pm2:** 1. Native Linux integration, no additional dependencies 2. Better OS-level security controls (ProtectSystem, ProtectHome) 3. Superior logging with journalctl integration 4. Standard across Linux distributions 5. More robust process management for production **Usage:** # Development: sudo ./scripts/install-systemd.sh dev # Production: sudo ./scripts/install-systemd.sh prod # View logs: sudo journalctl -u tractatus -f 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
94 lines
2.9 KiB
JavaScript
94 lines
2.9 KiB
JavaScript
/**
|
|
* Integration Tests - Health Check and Basic Infrastructure
|
|
* Verifies server starts and basic endpoints respond
|
|
*/
|
|
|
|
const request = require('supertest');
|
|
const app = require('../../src/server');
|
|
|
|
describe('Health Check Integration Tests', () => {
|
|
describe('GET /health', () => {
|
|
test('should return healthy status', async () => {
|
|
const response = await request(app)
|
|
.get('/health')
|
|
.expect('Content-Type', /json/)
|
|
.expect(200);
|
|
|
|
expect(response.body).toHaveProperty('status', 'healthy');
|
|
expect(response.body).toHaveProperty('timestamp');
|
|
expect(response.body).toHaveProperty('uptime');
|
|
expect(response.body).toHaveProperty('environment');
|
|
expect(typeof response.body.uptime).toBe('number');
|
|
});
|
|
});
|
|
|
|
describe('GET /api', () => {
|
|
test('should return API documentation', async () => {
|
|
const response = await request(app)
|
|
.get('/api')
|
|
.expect('Content-Type', /json/)
|
|
.expect(200);
|
|
|
|
expect(response.body).toHaveProperty('name', 'Tractatus AI Safety Framework API');
|
|
expect(response.body).toHaveProperty('version');
|
|
expect(response.body).toHaveProperty('endpoints');
|
|
});
|
|
});
|
|
|
|
describe('GET /', () => {
|
|
test('should return homepage', async () => {
|
|
const response = await request(app)
|
|
.get('/')
|
|
.expect(200);
|
|
|
|
expect(response.text).toContain('Tractatus AI Safety Framework');
|
|
// Homepage serves HTML, not text with "Server Running"
|
|
expect(response.headers['content-type']).toMatch(/html/);
|
|
});
|
|
});
|
|
|
|
describe('404 Handler', () => {
|
|
test('should return 404 for non-existent routes', async () => {
|
|
const response = await request(app)
|
|
.get('/this-route-does-not-exist')
|
|
.expect(404);
|
|
|
|
expect(response.body).toHaveProperty('error');
|
|
});
|
|
});
|
|
|
|
describe('Security Headers', () => {
|
|
test('should include security headers', async () => {
|
|
const response = await request(app)
|
|
.get('/health');
|
|
|
|
// Helmet security headers
|
|
expect(response.headers).toHaveProperty('x-content-type-options', 'nosniff');
|
|
expect(response.headers).toHaveProperty('x-frame-options');
|
|
expect(response.headers).toHaveProperty('x-xss-protection');
|
|
});
|
|
});
|
|
|
|
describe('CORS', () => {
|
|
test('should handle CORS preflight', async () => {
|
|
const response = await request(app)
|
|
.options('/api/documents')
|
|
.set('Origin', 'http://localhost:3000')
|
|
.set('Access-Control-Request-Method', 'GET');
|
|
|
|
// Should allow CORS
|
|
expect([200, 204]).toContain(response.status);
|
|
});
|
|
});
|
|
|
|
describe('MongoDB Connection', () => {
|
|
test('should connect to database', async () => {
|
|
const response = await request(app)
|
|
.get('/api/documents?limit=1')
|
|
.expect(200);
|
|
|
|
// If we get a successful response, MongoDB is connected
|
|
expect(response.body).toHaveProperty('success');
|
|
});
|
|
});
|
|
});
|