220 lines
8.9 KiB
JavaScript
220 lines
8.9 KiB
JavaScript
const axios = require('axios');
|
||
|
||
const BASE_URL = 'http://localhost:3000/api';
|
||
|
||
// Store session data for testing
|
||
let testSession = {
|
||
guestId: null,
|
||
sessionToken: null
|
||
};
|
||
|
||
// Helper function to print test results
|
||
function printTestResult(testNumber, testName, success, details = '') {
|
||
const emoji = success ? '✅' : '❌';
|
||
console.log(`\n${emoji} Test ${testNumber}: ${testName}`);
|
||
if (details) console.log(details);
|
||
}
|
||
|
||
// Helper function to print section header
|
||
function printSection(title) {
|
||
console.log('\n' + '='.repeat(60));
|
||
console.log(title);
|
||
console.log('='.repeat(60));
|
||
}
|
||
|
||
async function runTests() {
|
||
console.log('\n╔════════════════════════════════════════════════════════════╗');
|
||
console.log('║ Guest Quiz Limit Tests (Task 16) ║');
|
||
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
||
console.log('Make sure the server is running on http://localhost:3000\n');
|
||
|
||
try {
|
||
// Test 1: Create a guest session first
|
||
printSection('Test 1: Create guest session for testing');
|
||
try {
|
||
const response = await axios.post(`${BASE_URL}/guest/start-session`, {
|
||
deviceId: `test_device_${Date.now()}`
|
||
});
|
||
|
||
if (response.status === 201 && response.data.success) {
|
||
testSession.guestId = response.data.data.guestId;
|
||
testSession.sessionToken = response.data.data.sessionToken;
|
||
printTestResult(1, 'Guest session created', true,
|
||
`Guest ID: ${testSession.guestId}\nToken: ${testSession.sessionToken.substring(0, 50)}...`);
|
||
} else {
|
||
throw new Error('Failed to create session');
|
||
}
|
||
} catch (error) {
|
||
printTestResult(1, 'Guest session creation', false,
|
||
`Error: ${error.response?.data?.message || error.message}`);
|
||
return; // Can't continue without session
|
||
}
|
||
|
||
// Test 2: Check quiz limit with valid token (should have 3 remaining)
|
||
printSection('Test 2: Check quiz limit with valid token');
|
||
try {
|
||
const response = await axios.get(`${BASE_URL}/guest/quiz-limit`, {
|
||
headers: {
|
||
'X-Guest-Token': testSession.sessionToken
|
||
}
|
||
});
|
||
|
||
if (response.status === 200 && response.data.success) {
|
||
const { quizLimit, session } = response.data.data;
|
||
printTestResult(2, 'Quiz limit check with valid token', true,
|
||
`Max Quizzes: ${quizLimit.maxQuizzes}\n` +
|
||
`Quizzes Attempted: ${quizLimit.quizzesAttempted}\n` +
|
||
`Quizzes Remaining: ${quizLimit.quizzesRemaining}\n` +
|
||
`Has Reached Limit: ${quizLimit.hasReachedLimit}\n` +
|
||
`Time Remaining: ${session.timeRemaining}`);
|
||
} else {
|
||
throw new Error('Unexpected response');
|
||
}
|
||
} catch (error) {
|
||
printTestResult(2, 'Quiz limit check with valid token', false,
|
||
`Error: ${error.response?.data?.message || error.message}`);
|
||
}
|
||
|
||
// Test 3: Check quiz limit without token (should fail)
|
||
printSection('Test 3: Check quiz limit without token (should fail with 401)');
|
||
try {
|
||
const response = await axios.get(`${BASE_URL}/guest/quiz-limit`);
|
||
printTestResult(3, 'No token provided', false,
|
||
'Should have returned 401 but got: ' + response.status);
|
||
} catch (error) {
|
||
if (error.response?.status === 401) {
|
||
printTestResult(3, 'No token provided', true,
|
||
`Correctly returned 401: ${error.response.data.message}`);
|
||
} else {
|
||
printTestResult(3, 'No token provided', false,
|
||
`Wrong status code: ${error.response?.status || 'unknown'}`);
|
||
}
|
||
}
|
||
|
||
// Test 4: Check quiz limit with invalid token (should fail)
|
||
printSection('Test 4: Check quiz limit with invalid token (should fail with 401)');
|
||
try {
|
||
const response = await axios.get(`${BASE_URL}/guest/quiz-limit`, {
|
||
headers: {
|
||
'X-Guest-Token': 'invalid.token.here'
|
||
}
|
||
});
|
||
printTestResult(4, 'Invalid token provided', false,
|
||
'Should have returned 401 but got: ' + response.status);
|
||
} catch (error) {
|
||
if (error.response?.status === 401) {
|
||
printTestResult(4, 'Invalid token provided', true,
|
||
`Correctly returned 401: ${error.response.data.message}`);
|
||
} else {
|
||
printTestResult(4, 'Invalid token provided', false,
|
||
`Wrong status code: ${error.response?.status || 'unknown'}`);
|
||
}
|
||
}
|
||
|
||
// Test 5: Simulate reaching quiz limit
|
||
printSection('Test 5: Simulate quiz limit reached (update database manually)');
|
||
console.log('\nℹ️ To test limit reached scenario:');
|
||
console.log(' Run this SQL query:');
|
||
console.log(` UPDATE guest_sessions SET quizzes_attempted = 3 WHERE guest_id = '${testSession.guestId}';`);
|
||
console.log('\nℹ️ Then check quiz limit again with this curl command:');
|
||
console.log(` curl -H "X-Guest-Token: ${testSession.sessionToken}" ${BASE_URL}/guest/quiz-limit`);
|
||
console.log('\n Expected: hasReachedLimit: true, upgradePrompt with benefits');
|
||
|
||
// Test 6: Check with non-existent guest ID token
|
||
printSection('Test 6: Check with token for non-existent guest (should fail with 404)');
|
||
try {
|
||
// Create a token with fake guest ID
|
||
const jwt = require('jsonwebtoken');
|
||
const config = require('./config/config');
|
||
const fakeToken = jwt.sign(
|
||
{ guestId: 'guest_fake_12345' },
|
||
config.jwt.secret,
|
||
{ expiresIn: '24h' }
|
||
);
|
||
|
||
const response = await axios.get(`${BASE_URL}/guest/quiz-limit`, {
|
||
headers: {
|
||
'X-Guest-Token': fakeToken
|
||
}
|
||
});
|
||
printTestResult(6, 'Non-existent guest ID', false,
|
||
'Should have returned 404 but got: ' + response.status);
|
||
} catch (error) {
|
||
if (error.response?.status === 404) {
|
||
printTestResult(6, 'Non-existent guest ID', true,
|
||
`Correctly returned 404: ${error.response.data.message}`);
|
||
} else {
|
||
printTestResult(6, 'Non-existent guest ID', false,
|
||
`Wrong status code: ${error.response?.status || 'unknown'}`);
|
||
}
|
||
}
|
||
|
||
// Test 7: Verify response structure
|
||
printSection('Test 7: Verify response structure and data types');
|
||
try {
|
||
const response = await axios.get(`${BASE_URL}/guest/quiz-limit`, {
|
||
headers: {
|
||
'X-Guest-Token': testSession.sessionToken
|
||
}
|
||
});
|
||
|
||
const { data } = response.data;
|
||
const hasCorrectStructure =
|
||
data.guestId &&
|
||
data.quizLimit &&
|
||
typeof data.quizLimit.maxQuizzes === 'number' &&
|
||
typeof data.quizLimit.quizzesAttempted === 'number' &&
|
||
typeof data.quizLimit.quizzesRemaining === 'number' &&
|
||
typeof data.quizLimit.hasReachedLimit === 'boolean' &&
|
||
data.session &&
|
||
data.session.expiresAt &&
|
||
data.session.timeRemaining;
|
||
|
||
if (hasCorrectStructure) {
|
||
printTestResult(7, 'Response structure verification', true,
|
||
'All required fields present with correct types');
|
||
} else {
|
||
printTestResult(7, 'Response structure verification', false,
|
||
'Missing or incorrect fields in response');
|
||
}
|
||
} catch (error) {
|
||
printTestResult(7, 'Response structure verification', false,
|
||
`Error: ${error.message}`);
|
||
}
|
||
|
||
// Test 8: Verify calculations
|
||
printSection('Test 8: Verify quiz remaining calculation');
|
||
try {
|
||
const response = await axios.get(`${BASE_URL}/guest/quiz-limit`, {
|
||
headers: {
|
||
'X-Guest-Token': testSession.sessionToken
|
||
}
|
||
});
|
||
|
||
const { quizLimit } = response.data.data;
|
||
const expectedRemaining = quizLimit.maxQuizzes - quizLimit.quizzesAttempted;
|
||
|
||
if (quizLimit.quizzesRemaining === expectedRemaining) {
|
||
printTestResult(8, 'Quiz remaining calculation', true,
|
||
`Calculation correct: ${quizLimit.maxQuizzes} - ${quizLimit.quizzesAttempted} = ${quizLimit.quizzesRemaining}`);
|
||
} else {
|
||
printTestResult(8, 'Quiz remaining calculation', false,
|
||
`Expected ${expectedRemaining} but got ${quizLimit.quizzesRemaining}`);
|
||
}
|
||
} catch (error) {
|
||
printTestResult(8, 'Quiz remaining calculation', false,
|
||
`Error: ${error.message}`);
|
||
}
|
||
|
||
} catch (error) {
|
||
console.error('\n❌ Fatal error during testing:', error.message);
|
||
}
|
||
|
||
console.log('\n╔════════════════════════════════════════════════════════════╗');
|
||
console.log('║ Tests Completed ║');
|
||
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
||
}
|
||
|
||
// Run tests
|
||
runTests();
|