add changes

This commit is contained in:
AD2025
2025-12-25 00:24:11 +02:00
parent 079c10e843
commit efb4f69e20
64 changed files with 576 additions and 568 deletions

View File

@@ -0,0 +1,379 @@
const axios = require('axios');
const BASE_URL = 'http://localhost:3000/api';
// Test configuration
const testConfig = {
adminUser: {
email: 'admin@example.com',
password: 'Admin123!@#'
},
regularUser: {
email: 'stattest@example.com',
password: 'Test123!@#'
}
};
// Test state
let adminToken = null;
let regularToken = null;
// Test results
let passedTests = 0;
let failedTests = 0;
const results = [];
// Helper function to log test results
function logTest(name, passed, error = null) {
results.push({ name, passed, error });
if (passed) {
console.log(`${name}`);
passedTests++;
} else {
console.log(`${name}`);
if (error) console.log(` Error: ${error}`);
failedTests++;
}
}
// Setup function
async function setup() {
console.log('Setting up test data...\n');
try {
// Login admin user
const adminLoginRes = await axios.post(`${BASE_URL}/auth/login`, {
email: testConfig.adminUser.email,
password: testConfig.adminUser.password
});
adminToken = adminLoginRes.data.data.token;
console.log('✓ Admin user logged in');
// Login regular user
const userLoginRes = await axios.post(`${BASE_URL}/auth/login`, {
email: testConfig.regularUser.email,
password: testConfig.regularUser.password
});
regularToken = userLoginRes.data.data.token;
console.log('✓ Regular user logged in');
console.log('\n============================================================');
console.log('GUEST ANALYTICS API TESTS');
console.log('============================================================\n');
} catch (error) {
console.error('Setup failed:', error.response?.data || error.message);
process.exit(1);
}
}
// Test functions
async function testGetGuestAnalytics() {
try {
const response = await axios.get(`${BASE_URL}/admin/guest-analytics`, {
headers: { Authorization: `Bearer ${adminToken}` }
});
const passed = response.status === 200 &&
response.data.success === true &&
response.data.data !== undefined;
logTest('Get guest analytics', passed);
return response.data.data;
} catch (error) {
logTest('Get guest analytics', false, error.response?.data?.message || error.message);
return null;
}
}
async function testOverviewStructure(data) {
if (!data) {
logTest('Overview section structure', false, 'No data available');
return;
}
try {
const overview = data.overview;
const passed = overview !== undefined &&
typeof overview.totalGuestSessions === 'number' &&
typeof overview.activeGuestSessions === 'number' &&
typeof overview.expiredGuestSessions === 'number' &&
typeof overview.convertedGuestSessions === 'number' &&
typeof overview.conversionRate === 'number';
logTest('Overview section structure', passed);
} catch (error) {
logTest('Overview section structure', false, error.message);
}
}
async function testQuizActivityStructure(data) {
if (!data) {
logTest('Quiz activity section structure', false, 'No data available');
return;
}
try {
const quizActivity = data.quizActivity;
const passed = quizActivity !== undefined &&
typeof quizActivity.totalGuestQuizzes === 'number' &&
typeof quizActivity.completedGuestQuizzes === 'number' &&
typeof quizActivity.guestQuizCompletionRate === 'number' &&
typeof quizActivity.avgQuizzesPerGuest === 'number' &&
typeof quizActivity.avgQuizzesBeforeConversion === 'number';
logTest('Quiz activity section structure', passed);
} catch (error) {
logTest('Quiz activity section structure', false, error.message);
}
}
async function testBehaviorStructure(data) {
if (!data) {
logTest('Behavior section structure', false, 'No data available');
return;
}
try {
const behavior = data.behavior;
const passed = behavior !== undefined &&
typeof behavior.bounceRate === 'number' &&
typeof behavior.avgSessionDurationMinutes === 'number';
logTest('Behavior section structure', passed);
} catch (error) {
logTest('Behavior section structure', false, error.message);
}
}
async function testRecentActivityStructure(data) {
if (!data) {
logTest('Recent activity section structure', false, 'No data available');
return;
}
try {
const recentActivity = data.recentActivity;
const passed = recentActivity !== undefined &&
recentActivity.last30Days !== undefined &&
typeof recentActivity.last30Days.newGuestSessions === 'number' &&
typeof recentActivity.last30Days.conversions === 'number';
logTest('Recent activity section structure', passed);
} catch (error) {
logTest('Recent activity section structure', false, error.message);
}
}
async function testConversionRateCalculation(data) {
if (!data) {
logTest('Conversion rate calculation', false, 'No data available');
return;
}
try {
const overview = data.overview;
const expectedRate = overview.totalGuestSessions > 0
? ((overview.convertedGuestSessions / overview.totalGuestSessions) * 100)
: 0;
// Allow small floating point difference
const passed = Math.abs(overview.conversionRate - expectedRate) < 0.01 &&
overview.conversionRate >= 0 &&
overview.conversionRate <= 100;
logTest('Conversion rate calculation', passed);
} catch (error) {
logTest('Conversion rate calculation', false, error.message);
}
}
async function testQuizCompletionRateCalculation(data) {
if (!data) {
logTest('Quiz completion rate calculation', false, 'No data available');
return;
}
try {
const quizActivity = data.quizActivity;
const expectedRate = quizActivity.totalGuestQuizzes > 0
? ((quizActivity.completedGuestQuizzes / quizActivity.totalGuestQuizzes) * 100)
: 0;
// Allow small floating point difference
const passed = Math.abs(quizActivity.guestQuizCompletionRate - expectedRate) < 0.01 &&
quizActivity.guestQuizCompletionRate >= 0 &&
quizActivity.guestQuizCompletionRate <= 100;
logTest('Quiz completion rate calculation', passed);
} catch (error) {
logTest('Quiz completion rate calculation', false, error.message);
}
}
async function testBounceRateRange(data) {
if (!data) {
logTest('Bounce rate in valid range', false, 'No data available');
return;
}
try {
const bounceRate = data.behavior.bounceRate;
const passed = bounceRate >= 0 && bounceRate <= 100;
logTest('Bounce rate in valid range', passed);
} catch (error) {
logTest('Bounce rate in valid range', false, error.message);
}
}
async function testAveragesAreNonNegative(data) {
if (!data) {
logTest('Average values are non-negative', false, 'No data available');
return;
}
try {
const passed = data.quizActivity.avgQuizzesPerGuest >= 0 &&
data.quizActivity.avgQuizzesBeforeConversion >= 0 &&
data.behavior.avgSessionDurationMinutes >= 0;
logTest('Average values are non-negative', passed);
} catch (error) {
logTest('Average values are non-negative', false, error.message);
}
}
async function testSessionCounts(data) {
if (!data) {
logTest('Session counts are consistent', false, 'No data available');
return;
}
try {
const overview = data.overview;
// Total should be >= sum of active, expired, and converted (some might be both expired and converted)
const passed = overview.totalGuestSessions >= 0 &&
overview.activeGuestSessions >= 0 &&
overview.expiredGuestSessions >= 0 &&
overview.convertedGuestSessions >= 0 &&
overview.convertedGuestSessions <= overview.totalGuestSessions;
logTest('Session counts are consistent', passed);
} catch (error) {
logTest('Session counts are consistent', false, error.message);
}
}
async function testQuizCounts(data) {
if (!data) {
logTest('Quiz counts are consistent', false, 'No data available');
return;
}
try {
const quizActivity = data.quizActivity;
const passed = quizActivity.totalGuestQuizzes >= 0 &&
quizActivity.completedGuestQuizzes >= 0 &&
quizActivity.completedGuestQuizzes <= quizActivity.totalGuestQuizzes;
logTest('Quiz counts are consistent', passed);
} catch (error) {
logTest('Quiz counts are consistent', false, error.message);
}
}
async function testNonAdminBlocked() {
try {
await axios.get(`${BASE_URL}/admin/guest-analytics`, {
headers: { Authorization: `Bearer ${regularToken}` }
});
logTest('Non-admin user blocked', false, 'Regular user should not have access');
} catch (error) {
const passed = error.response?.status === 403;
logTest('Non-admin user blocked', passed,
!passed ? `Expected 403, got ${error.response?.status}` : null);
}
}
async function testUnauthenticated() {
try {
await axios.get(`${BASE_URL}/admin/guest-analytics`);
logTest('Unauthenticated request blocked', false, 'Should require authentication');
} catch (error) {
const passed = error.response?.status === 401;
logTest('Unauthenticated request blocked', passed,
!passed ? `Expected 401, got ${error.response?.status}` : null);
}
}
// Main test runner
async function runTests() {
await setup();
console.log('Running tests...\n');
// Get analytics data
const data = await testGetGuestAnalytics();
await new Promise(resolve => setTimeout(resolve, 100));
// Structure validation tests
await testOverviewStructure(data);
await new Promise(resolve => setTimeout(resolve, 100));
await testQuizActivityStructure(data);
await new Promise(resolve => setTimeout(resolve, 100));
await testBehaviorStructure(data);
await new Promise(resolve => setTimeout(resolve, 100));
await testRecentActivityStructure(data);
await new Promise(resolve => setTimeout(resolve, 100));
// Calculation validation tests
await testConversionRateCalculation(data);
await new Promise(resolve => setTimeout(resolve, 100));
await testQuizCompletionRateCalculation(data);
await new Promise(resolve => setTimeout(resolve, 100));
await testBounceRateRange(data);
await new Promise(resolve => setTimeout(resolve, 100));
await testAveragesAreNonNegative(data);
await new Promise(resolve => setTimeout(resolve, 100));
// Consistency tests
await testSessionCounts(data);
await new Promise(resolve => setTimeout(resolve, 100));
await testQuizCounts(data);
await new Promise(resolve => setTimeout(resolve, 100));
// Authorization tests
await testNonAdminBlocked();
await new Promise(resolve => setTimeout(resolve, 100));
await testUnauthenticated();
// Print results
console.log('\n============================================================');
console.log(`RESULTS: ${passedTests} passed, ${failedTests} failed out of ${passedTests + failedTests} tests`);
console.log('============================================================\n');
if (failedTests > 0) {
console.log('Failed tests:');
results.filter(r => !r.passed).forEach(r => {
console.log(` - ${r.name}`);
if (r.error) console.log(` ${r.error}`);
});
}
process.exit(failedTests > 0 ? 1 : 0);
}
// Run tests
runTests().catch(error => {
console.error('Test execution failed:', error);
process.exit(1);
});