add changes
This commit is contained in:
309
backend/tests/test-guest-conversion.js
Normal file
309
backend/tests/test-guest-conversion.js
Normal file
@@ -0,0 +1,309 @@
|
||||
const axios = require('axios');
|
||||
|
||||
const BASE_URL = 'http://localhost:3000/api';
|
||||
|
||||
// Store test data
|
||||
let testData = {
|
||||
guestId: null,
|
||||
sessionToken: null,
|
||||
userId: null,
|
||||
userToken: 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 to User Conversion Tests (Task 17) ║');
|
||||
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
||||
console.log('Make sure the server is running on http://localhost:3000\n');
|
||||
|
||||
try {
|
||||
// Test 1: Create a guest session
|
||||
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) {
|
||||
testData.guestId = response.data.data.guestId;
|
||||
testData.sessionToken = response.data.data.sessionToken;
|
||||
printTestResult(1, 'Guest session created', true,
|
||||
`Guest ID: ${testData.guestId}\nToken: ${testData.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;
|
||||
}
|
||||
|
||||
// Test 2: Try conversion without required fields
|
||||
printSection('Test 2: Conversion without required fields (should fail)');
|
||||
try {
|
||||
const response = await axios.post(`${BASE_URL}/guest/convert`, {
|
||||
username: 'testuser'
|
||||
// Missing email and password
|
||||
}, {
|
||||
headers: {
|
||||
'X-Guest-Token': testData.sessionToken
|
||||
}
|
||||
});
|
||||
printTestResult(2, 'Missing required fields', false,
|
||||
'Should have returned 400 but got: ' + response.status);
|
||||
} catch (error) {
|
||||
if (error.response?.status === 400) {
|
||||
printTestResult(2, 'Missing required fields', true,
|
||||
`Correctly returned 400: ${error.response.data.message}`);
|
||||
} else {
|
||||
printTestResult(2, 'Missing required fields', false,
|
||||
`Wrong status code: ${error.response?.status || 'unknown'}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 3: Try conversion with invalid email
|
||||
printSection('Test 3: Conversion with invalid email (should fail)');
|
||||
try {
|
||||
const response = await axios.post(`${BASE_URL}/guest/convert`, {
|
||||
username: 'testuser',
|
||||
email: 'invalid-email',
|
||||
password: 'Password123'
|
||||
}, {
|
||||
headers: {
|
||||
'X-Guest-Token': testData.sessionToken
|
||||
}
|
||||
});
|
||||
printTestResult(3, 'Invalid email format', false,
|
||||
'Should have returned 400 but got: ' + response.status);
|
||||
} catch (error) {
|
||||
if (error.response?.status === 400) {
|
||||
printTestResult(3, 'Invalid email format', true,
|
||||
`Correctly returned 400: ${error.response.data.message}`);
|
||||
} else {
|
||||
printTestResult(3, 'Invalid email format', false,
|
||||
`Wrong status code: ${error.response?.status || 'unknown'}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 4: Try conversion with weak password
|
||||
printSection('Test 4: Conversion with weak password (should fail)');
|
||||
try {
|
||||
const response = await axios.post(`${BASE_URL}/guest/convert`, {
|
||||
username: 'testuser',
|
||||
email: 'test@example.com',
|
||||
password: 'weak'
|
||||
}, {
|
||||
headers: {
|
||||
'X-Guest-Token': testData.sessionToken
|
||||
}
|
||||
});
|
||||
printTestResult(4, 'Weak password', false,
|
||||
'Should have returned 400 but got: ' + response.status);
|
||||
} catch (error) {
|
||||
if (error.response?.status === 400) {
|
||||
printTestResult(4, 'Weak password', true,
|
||||
`Correctly returned 400: ${error.response.data.message}`);
|
||||
} else {
|
||||
printTestResult(4, 'Weak password', false,
|
||||
`Wrong status code: ${error.response?.status || 'unknown'}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 5: Successful conversion
|
||||
printSection('Test 5: Successful guest to user conversion');
|
||||
const timestamp = Date.now();
|
||||
const conversionData = {
|
||||
username: `converted${timestamp}`,
|
||||
email: `converted${timestamp}@test.com`,
|
||||
password: 'Password123'
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await axios.post(`${BASE_URL}/guest/convert`, conversionData, {
|
||||
headers: {
|
||||
'X-Guest-Token': testData.sessionToken
|
||||
}
|
||||
});
|
||||
|
||||
if (response.status === 201 && response.data.success) {
|
||||
testData.userId = response.data.data.user.id;
|
||||
testData.userToken = response.data.data.token;
|
||||
|
||||
printTestResult(5, 'Guest to user conversion', true,
|
||||
`User ID: ${testData.userId}\n` +
|
||||
`Username: ${response.data.data.user.username}\n` +
|
||||
`Email: ${response.data.data.user.email}\n` +
|
||||
`Quizzes Transferred: ${response.data.data.migration.quizzesTransferred}\n` +
|
||||
`Token: ${testData.userToken.substring(0, 50)}...`);
|
||||
|
||||
console.log('\nMigration Stats:');
|
||||
const stats = response.data.data.migration.stats;
|
||||
console.log(` Total Quizzes: ${stats.totalQuizzes}`);
|
||||
console.log(` Quizzes Passed: ${stats.quizzesPassed}`);
|
||||
console.log(` Questions Answered: ${stats.totalQuestionsAnswered}`);
|
||||
console.log(` Correct Answers: ${stats.correctAnswers}`);
|
||||
console.log(` Accuracy: ${stats.accuracy}%`);
|
||||
} else {
|
||||
throw new Error('Unexpected response');
|
||||
}
|
||||
} catch (error) {
|
||||
printTestResult(5, 'Guest to user conversion', false,
|
||||
`Error: ${error.response?.data?.message || error.message}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Test 6: Try to convert the same guest session again (should fail)
|
||||
printSection('Test 6: Try to convert already converted session (should fail)');
|
||||
try {
|
||||
const response = await axios.post(`${BASE_URL}/guest/convert`, {
|
||||
username: `another${timestamp}`,
|
||||
email: `another${timestamp}@test.com`,
|
||||
password: 'Password123'
|
||||
}, {
|
||||
headers: {
|
||||
'X-Guest-Token': testData.sessionToken
|
||||
}
|
||||
});
|
||||
printTestResult(6, 'Already converted session', false,
|
||||
'Should have returned 410 but got: ' + response.status);
|
||||
} catch (error) {
|
||||
if (error.response?.status === 410) {
|
||||
printTestResult(6, 'Already converted session', true,
|
||||
`Correctly returned 410: ${error.response.data.message}`);
|
||||
} else {
|
||||
printTestResult(6, 'Already converted session', false,
|
||||
`Wrong status code: ${error.response?.status || 'unknown'}\nMessage: ${error.response?.data?.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 7: Try conversion with duplicate email
|
||||
printSection('Test 7: Create new guest and try conversion with duplicate email');
|
||||
try {
|
||||
// Create new guest session
|
||||
const guestResponse = await axios.post(`${BASE_URL}/guest/start-session`, {
|
||||
deviceId: `test_device_2_${Date.now()}`
|
||||
});
|
||||
|
||||
const newGuestToken = guestResponse.data.data.sessionToken;
|
||||
|
||||
// Try to convert with existing email
|
||||
const response = await axios.post(`${BASE_URL}/guest/convert`, {
|
||||
username: `unique${Date.now()}`,
|
||||
email: conversionData.email, // Use email from Test 5
|
||||
password: 'Password123'
|
||||
}, {
|
||||
headers: {
|
||||
'X-Guest-Token': newGuestToken
|
||||
}
|
||||
});
|
||||
|
||||
printTestResult(7, 'Duplicate email rejection', false,
|
||||
'Should have returned 400 but got: ' + response.status);
|
||||
} catch (error) {
|
||||
if (error.response?.status === 400 && error.response.data.message.includes('Email already registered')) {
|
||||
printTestResult(7, 'Duplicate email rejection', true,
|
||||
`Correctly returned 400: ${error.response.data.message}`);
|
||||
} else {
|
||||
printTestResult(7, 'Duplicate email rejection', false,
|
||||
`Wrong status code or message: ${error.response?.status || 'unknown'}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 8: Try conversion with duplicate username
|
||||
printSection('Test 8: Try conversion with duplicate username');
|
||||
try {
|
||||
// Create new guest session
|
||||
const guestResponse = await axios.post(`${BASE_URL}/guest/start-session`, {
|
||||
deviceId: `test_device_3_${Date.now()}`
|
||||
});
|
||||
|
||||
const newGuestToken = guestResponse.data.data.sessionToken;
|
||||
|
||||
// Try to convert with existing username
|
||||
const response = await axios.post(`${BASE_URL}/guest/convert`, {
|
||||
username: conversionData.username, // Use username from Test 5
|
||||
email: `unique${Date.now()}@test.com`,
|
||||
password: 'Password123'
|
||||
}, {
|
||||
headers: {
|
||||
'X-Guest-Token': newGuestToken
|
||||
}
|
||||
});
|
||||
|
||||
printTestResult(8, 'Duplicate username rejection', false,
|
||||
'Should have returned 400 but got: ' + response.status);
|
||||
} catch (error) {
|
||||
if (error.response?.status === 400 && error.response.data.message.includes('Username already taken')) {
|
||||
printTestResult(8, 'Duplicate username rejection', true,
|
||||
`Correctly returned 400: ${error.response.data.message}`);
|
||||
} else {
|
||||
printTestResult(8, 'Duplicate username rejection', false,
|
||||
`Wrong status code or message: ${error.response?.status || 'unknown'}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 9: Verify user can login with new credentials
|
||||
printSection('Test 9: Verify converted user can login');
|
||||
try {
|
||||
const response = await axios.post(`${BASE_URL}/auth/login`, {
|
||||
email: conversionData.email,
|
||||
password: conversionData.password
|
||||
});
|
||||
|
||||
if (response.status === 200 && response.data.success) {
|
||||
printTestResult(9, 'Login with converted credentials', true,
|
||||
`Successfully logged in as: ${response.data.data.user.username}\n` +
|
||||
`User ID matches: ${response.data.data.user.id === testData.userId}`);
|
||||
} else {
|
||||
throw new Error('Login failed');
|
||||
}
|
||||
} catch (error) {
|
||||
printTestResult(9, 'Login with converted credentials', false,
|
||||
`Error: ${error.response?.data?.message || error.message}`);
|
||||
}
|
||||
|
||||
// Test 10: Verify conversion without token (should fail)
|
||||
printSection('Test 10: Try conversion without guest token (should fail)');
|
||||
try {
|
||||
const response = await axios.post(`${BASE_URL}/guest/convert`, {
|
||||
username: `notoken${Date.now()}`,
|
||||
email: `notoken${Date.now()}@test.com`,
|
||||
password: 'Password123'
|
||||
});
|
||||
printTestResult(10, 'No guest token provided', false,
|
||||
'Should have returned 401 but got: ' + response.status);
|
||||
} catch (error) {
|
||||
if (error.response?.status === 401) {
|
||||
printTestResult(10, 'No guest token provided', true,
|
||||
`Correctly returned 401: ${error.response.data.message}`);
|
||||
} else {
|
||||
printTestResult(10, 'No guest token provided', false,
|
||||
`Wrong status code: ${error.response?.status || 'unknown'}`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n❌ Fatal error during testing:', error.message);
|
||||
}
|
||||
|
||||
console.log('\n╔════════════════════════════════════════════════════════════╗');
|
||||
console.log('║ Tests Completed ║');
|
||||
console.log('╚════════════════════════════════════════════════════════════╝\n');
|
||||
}
|
||||
|
||||
// Run tests
|
||||
runTests();
|
||||
Reference in New Issue
Block a user