You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

294 lines
7.3 KiB

#!/usr/bin/env node
/**
* Test API Demo Script
*
* Demonstrates the Test API Server functionality
* and validates all endpoints work correctly.
*
* @author Matthew Raymer
* @version 1.0.0
*/
const fetch = require('node-fetch');
const API_BASE_URL = 'http://localhost:3001';
/**
* Make HTTP request with timeout
* @param {string} url - Request URL
* @param {Object} options - Fetch options
* @returns {Promise<Object>} Response data
*/
async function makeRequest(url, options = {}) {
try {
const response = await fetch(url, {
timeout: 10000,
...options
});
const data = await response.json();
return {
status: response.status,
data,
headers: Object.fromEntries(response.headers.entries())
};
} catch (error) {
return {
status: 0,
error: error.message
};
}
}
/**
* Test health endpoint
*/
async function testHealth() {
console.log('🔍 Testing health endpoint...');
const result = await makeRequest(`${API_BASE_URL}/health`);
if (result.error) {
console.error('❌ Health check failed:', result.error);
return false;
}
console.log('✅ Health check passed');
console.log(' Status:', result.status);
console.log(' Version:', result.data.version);
console.log(' Endpoints:', Object.keys(result.data.endpoints).length);
return true;
}
/**
* Test content fetching
*/
async function testContentFetching() {
console.log('\n📱 Testing content fetching...');
const slotId = 'slot-08:00';
const result = await makeRequest(`${API_BASE_URL}/api/content/${slotId}`);
if (result.error) {
console.error('❌ Content fetch failed:', result.error);
return false;
}
console.log('✅ Content fetch passed');
console.log(' Status:', result.status);
console.log(' Slot ID:', result.data.slotId);
console.log(' Title:', result.data.title);
console.log(' ETag:', result.headers.etag);
return result.headers.etag;
}
/**
* Test ETag caching
*/
async function testETagCaching(etag) {
console.log('\n🔄 Testing ETag caching...');
const slotId = 'slot-08:00';
const result = await makeRequest(`${API_BASE_URL}/api/content/${slotId}`, {
headers: {
'If-None-Match': etag
}
});
if (result.error) {
console.error('❌ ETag test failed:', result.error);
return false;
}
if (result.status === 304) {
console.log('✅ ETag caching works (304 Not Modified)');
return true;
} else {
console.log('⚠️ ETag caching unexpected response:', result.status);
return false;
}
}
/**
* Test error scenarios
*/
async function testErrorScenarios() {
console.log('\n🚨 Testing error scenarios...');
const errorTypes = ['server-error', 'not-found', 'rate-limit', 'unauthorized'];
let passed = 0;
for (const errorType of errorTypes) {
const result = await makeRequest(`${API_BASE_URL}/api/error/${errorType}`);
if (result.error) {
console.log(`${errorType}: ${result.error}`);
} else {
console.log(`${errorType}: ${result.status}`);
passed++;
}
}
console.log(` Passed: ${passed}/${errorTypes.length}`);
return passed === errorTypes.length;
}
/**
* Test metrics endpoint
*/
async function testMetrics() {
console.log('\n📊 Testing metrics endpoint...');
const result = await makeRequest(`${API_BASE_URL}/api/metrics`);
if (result.error) {
console.error('❌ Metrics test failed:', result.error);
return false;
}
console.log('✅ Metrics endpoint works');
console.log(' Content store size:', result.data.contentStore.size);
console.log(' ETag store size:', result.data.etagStore.size);
console.log(' Uptime:', Math.round(result.data.uptime), 'seconds');
return true;
}
/**
* Test content update
*/
async function testContentUpdate() {
console.log('\n✏️ Testing content update...');
const slotId = 'slot-08:00';
const newContent = {
content: {
title: 'Updated Test Title',
body: 'This is updated test content',
timestamp: Date.now()
}
};
const result = await makeRequest(`${API_BASE_URL}/api/content/${slotId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(newContent)
});
if (result.error) {
console.error('❌ Content update failed:', result.error);
return false;
}
console.log('✅ Content update works');
console.log(' Status:', result.status);
console.log(' New ETag:', result.data.etag);
return true;
}
/**
* Test content clearing
*/
async function testContentClearing() {
console.log('\n🗑️ Testing content clearing...');
const result = await makeRequest(`${API_BASE_URL}/api/content`, {
method: 'DELETE'
});
if (result.error) {
console.error('❌ Content clearing failed:', result.error);
return false;
}
console.log('✅ Content clearing works');
console.log(' Status:', result.status);
return true;
}
/**
* Main test runner
*/
async function runTests() {
console.log('🚀 Starting Test API validation...\n');
const tests = [
{ name: 'Health Check', fn: testHealth },
{ name: 'Content Fetching', fn: testContentFetching },
{ name: 'ETag Caching', fn: testETagCaching },
{ name: 'Error Scenarios', fn: testErrorScenarios },
{ name: 'Metrics', fn: testMetrics },
{ name: 'Content Update', fn: testContentUpdate },
{ name: 'Content Clearing', fn: testContentClearing }
];
let passed = 0;
let etag = null;
for (const test of tests) {
try {
if (test.name === 'ETag Caching' && etag) {
const result = await test.fn(etag);
if (result) passed++;
} else {
const result = await test.fn();
if (result) {
passed++;
if (test.name === 'Content Fetching' && typeof result === 'string') {
etag = result;
}
}
}
} catch (error) {
console.error(`${test.name} failed with error:`, error.message);
}
}
console.log(`\n📋 Test Results: ${passed}/${tests.length} passed`);
if (passed === tests.length) {
console.log('🎉 All tests passed! Test API is working correctly.');
} else {
console.log('⚠️ Some tests failed. Check the output above for details.');
}
console.log('\n💡 Next steps:');
console.log(' 1. Start your test app');
console.log(' 2. Configure it to use this API');
console.log(' 3. Test plugin functionality');
console.log(' 4. Monitor API metrics at /api/metrics');
}
// Check if API server is running
async function checkServer() {
try {
const result = await makeRequest(`${API_BASE_URL}/health`);
if (result.error) {
console.error('❌ Cannot connect to Test API Server');
console.error(' Make sure the server is running: npm start');
console.error(' Server should be available at:', API_BASE_URL);
process.exit(1);
}
} catch (error) {
console.error('❌ Cannot connect to Test API Server');
console.error(' Make sure the server is running: npm start');
console.error(' Server should be available at:', API_BASE_URL);
process.exit(1);
}
}
// Run tests
checkServer().then(() => {
runTests().catch(error => {
console.error('❌ Test runner failed:', error.message);
process.exit(1);
});
});