Files
tasks-backend/tests/test-guest-endpoints.js
2025-12-26 23:56:32 +02:00

335 lines
13 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Manual Test Script for Guest Session Endpoints
* Task 15: Guest Session Creation
*
* Run this script with: node test-guest-endpoints.js
* Make sure the server is running on http://localhost:3000
*/
const axios = require('axios');
const API_BASE = 'http://localhost:3000/api';
let testGuestId = null;
let testSessionToken = null;
// Helper function for test output
function logTest(testNumber, description) {
console.log(`\n${'='.repeat(60)}`);
console.log(`${testNumber} Testing ${description}`);
console.log('='.repeat(60));
}
function logSuccess(message) {
console.log(`✅ SUCCESS: ${message}`);
}
function logError(message, error = null) {
console.log(`❌ ERROR: ${message}`);
if (error) {
if (error.response && error.response.data) {
console.log(`Response status: ${error.response.status}`);
console.log(`Response data:`, JSON.stringify(error.response.data, null, 2));
} else if (error.message) {
console.log(`Error details: ${error.message}`);
} else {
console.log(`Error:`, error);
}
}
}
// Test 1: Start a guest session
async function test1_StartGuestSession() {
logTest('1⃣', 'POST /api/guest/start-session - Create guest session');
try {
const requestData = {
deviceId: `device_${Date.now()}`
};
console.log('Request:', JSON.stringify(requestData, null, 2));
const response = await axios.post(`${API_BASE}/guest/start-session`, requestData);
console.log('Response:', JSON.stringify(response.data, null, 2));
if (response.data.success && response.data.data.guestId && response.data.data.sessionToken) {
testGuestId = response.data.data.guestId;
testSessionToken = response.data.data.sessionToken;
logSuccess('Guest session created successfully');
console.log('Guest ID:', testGuestId);
console.log('Session Token:', testSessionToken.substring(0, 50) + '...');
console.log('Expires In:', response.data.data.expiresIn);
console.log('Max Quizzes:', response.data.data.restrictions.maxQuizzes);
console.log('Quizzes Remaining:', response.data.data.restrictions.quizzesRemaining);
console.log('Available Categories:', response.data.data.availableCategories.length);
// Check restrictions
const features = response.data.data.restrictions.features;
console.log('\nFeatures:');
console.log(' - Can Take Quizzes:', features.canTakeQuizzes ? '✅' : '❌');
console.log(' - Can View Results:', features.canViewResults ? '✅' : '❌');
console.log(' - Can Bookmark Questions:', features.canBookmarkQuestions ? '✅' : '❌');
console.log(' - Can Track Progress:', features.canTrackProgress ? '✅' : '❌');
console.log(' - Can Earn Achievements:', features.canEarnAchievements ? '✅' : '❌');
} else {
logError('Unexpected response format');
}
} catch (error) {
logError('Failed to create guest session', error);
}
}
// Test 2: Get guest session details
async function test2_GetGuestSession() {
logTest('2⃣', 'GET /api/guest/session/:guestId - Get session details');
if (!testGuestId) {
logError('No guest ID available. Skipping test.');
return;
}
try {
const response = await axios.get(`${API_BASE}/guest/session/${testGuestId}`);
console.log('Response:', JSON.stringify(response.data, null, 2));
if (response.data.success && response.data.data) {
logSuccess('Guest session retrieved successfully');
console.log('Guest ID:', response.data.data.guestId);
console.log('Expires In:', response.data.data.expiresIn);
console.log('Is Expired:', response.data.data.isExpired);
console.log('Quizzes Attempted:', response.data.data.restrictions.quizzesAttempted);
console.log('Quizzes Remaining:', response.data.data.restrictions.quizzesRemaining);
console.log('Can Take Quizzes:', response.data.data.restrictions.features.canTakeQuizzes);
} else {
logError('Unexpected response format');
}
} catch (error) {
logError('Failed to get guest session', error);
}
}
// Test 3: Get non-existent guest session
async function test3_GetNonExistentSession() {
logTest('3⃣', 'GET /api/guest/session/:guestId - Non-existent session (should fail)');
try {
const response = await axios.get(`${API_BASE}/guest/session/guest_nonexistent_12345`);
console.log('Response:', JSON.stringify(response.data, null, 2));
logError('Should have returned 404 for non-existent session');
} catch (error) {
if (error.response && error.response.status === 404) {
console.log('Response:', JSON.stringify(error.response.data, null, 2));
logSuccess('Correctly returned 404 for non-existent session');
} else {
logError('Unexpected error', error);
}
}
}
// Test 4: Start guest session without deviceId (optional field)
async function test4_StartSessionWithoutDeviceId() {
logTest('4⃣', 'POST /api/guest/start-session - Without deviceId');
try {
const response = await axios.post(`${API_BASE}/guest/start-session`, {});
console.log('Response:', JSON.stringify(response.data, null, 2));
if (response.data.success && response.data.data.guestId) {
logSuccess('Guest session created without deviceId (optional field)');
console.log('Guest ID:', response.data.data.guestId);
} else {
logError('Unexpected response format');
}
} catch (error) {
logError('Failed to create guest session', error);
}
}
// Test 5: Verify guest-accessible categories
async function test5_VerifyGuestCategories() {
logTest('5⃣', 'Verify guest-accessible categories');
if (!testGuestId) {
logError('No guest ID available. Skipping test.');
return;
}
try {
const response = await axios.get(`${API_BASE}/guest/session/${testGuestId}`);
const categories = response.data.data.availableCategories;
console.log(`Found ${categories.length} guest-accessible categories:`);
categories.forEach((cat, index) => {
console.log(` ${index + 1}. ${cat.name} (${cat.question_count} questions)`);
});
if (categories.length > 0) {
logSuccess(`${categories.length} guest-accessible categories available`);
// Expected categories from seeder: JavaScript, Angular, React
const expectedCategories = ['JavaScript', 'Angular', 'React'];
const foundCategories = categories.map(c => c.name);
console.log('\nExpected guest-accessible categories:', expectedCategories.join(', '));
console.log('Found categories:', foundCategories.join(', '));
const allFound = expectedCategories.every(cat => foundCategories.includes(cat));
if (allFound) {
logSuccess('All expected categories are accessible to guests');
} else {
logError('Some expected categories are missing');
}
} else {
logError('No guest-accessible categories found (check seeder data)');
}
} catch (error) {
logError('Failed to verify categories', error);
}
}
// Test 6: Verify session restrictions
async function test6_VerifySessionRestrictions() {
logTest('6⃣', 'Verify guest session restrictions');
if (!testGuestId) {
logError('No guest ID available. Skipping test.');
return;
}
try {
const response = await axios.get(`${API_BASE}/guest/session/${testGuestId}`);
const restrictions = response.data.data.restrictions;
const features = restrictions.features;
console.log('Quiz Restrictions:');
console.log(' - Max Quizzes:', restrictions.maxQuizzes);
console.log(' - Quizzes Attempted:', restrictions.quizzesAttempted);
console.log(' - Quizzes Remaining:', restrictions.quizzesRemaining);
console.log('\nFeature Restrictions:');
console.log(' - Can Take Quizzes:', features.canTakeQuizzes ? '✅ Yes' : '❌ No');
console.log(' - Can View Results:', features.canViewResults ? '✅ Yes' : '❌ No');
console.log(' - Can Bookmark Questions:', features.canBookmarkQuestions ? '✅ Yes' : '❌ No');
console.log(' - Can Track Progress:', features.canTrackProgress ? '✅ Yes' : '❌ No');
console.log(' - Can Earn Achievements:', features.canEarnAchievements ? '✅ Yes' : '❌ No');
// Verify expected restrictions
const expectedRestrictions = {
maxQuizzes: 3,
canTakeQuizzes: true,
canViewResults: true,
canBookmarkQuestions: false,
canTrackProgress: false,
canEarnAchievements: false
};
const allCorrect =
restrictions.maxQuizzes === expectedRestrictions.maxQuizzes &&
features.canTakeQuizzes === expectedRestrictions.canTakeQuizzes &&
features.canViewResults === expectedRestrictions.canViewResults &&
features.canBookmarkQuestions === expectedRestrictions.canBookmarkQuestions &&
features.canTrackProgress === expectedRestrictions.canTrackProgress &&
features.canEarnAchievements === expectedRestrictions.canEarnAchievements;
if (allCorrect) {
logSuccess('All restrictions are correctly configured');
} else {
logError('Some restrictions do not match expected values');
}
} catch (error) {
logError('Failed to verify restrictions', error);
}
}
// Test 7: Verify session token is valid JWT
async function test7_VerifySessionToken() {
logTest('7⃣', 'Verify session token format');
if (!testSessionToken) {
logError('No session token available. Skipping test.');
return;
}
try {
// JWT tokens have 3 parts separated by dots
const parts = testSessionToken.split('.');
console.log('Token parts:', parts.length);
console.log('Header:', parts[0].substring(0, 20) + '...');
console.log('Payload:', parts[1].substring(0, 20) + '...');
console.log('Signature:', parts[2].substring(0, 20) + '...');
if (parts.length === 3) {
logSuccess('Session token is in valid JWT format (3 parts)');
// Decode payload (base64)
try {
const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString());
console.log('\nDecoded payload:');
console.log(' - Guest ID:', payload.guestId);
console.log(' - Issued At:', new Date(payload.iat * 1000).toISOString());
console.log(' - Expires At:', new Date(payload.exp * 1000).toISOString());
if (payload.guestId === testGuestId) {
logSuccess('Token contains correct guest ID');
} else {
logError('Token guest ID does not match session guest ID');
}
} catch (decodeError) {
logError('Failed to decode token payload', decodeError);
}
} else {
logError('Session token is not in valid JWT format');
}
} catch (error) {
logError('Failed to verify token', error);
}
}
// Run all tests
async function runAllTests() {
console.log('\n');
console.log('╔════════════════════════════════════════════════════════════╗');
console.log('║ Guest Session Creation Tests (Task 15) ║');
console.log('╚════════════════════════════════════════════════════════════╝');
console.log('\nMake sure the server is running on http://localhost:3000\n');
await test1_StartGuestSession();
await new Promise(resolve => setTimeout(resolve, 500));
await test2_GetGuestSession();
await new Promise(resolve => setTimeout(resolve, 500));
await test3_GetNonExistentSession();
await new Promise(resolve => setTimeout(resolve, 500));
await test4_StartSessionWithoutDeviceId();
await new Promise(resolve => setTimeout(resolve, 500));
await test5_VerifyGuestCategories();
await new Promise(resolve => setTimeout(resolve, 500));
await test6_VerifySessionRestrictions();
await new Promise(resolve => setTimeout(resolve, 500));
await test7_VerifySessionToken();
console.log('\n');
console.log('╔════════════════════════════════════════════════════════════╗');
console.log('║ All Tests Completed ║');
console.log('╚════════════════════════════════════════════════════════════╝');
console.log('\n');
}
// Run tests
runAllTests().catch(error => {
console.error('\n❌ Fatal error running tests:', error);
process.exit(1);
});