480 lines
15 KiB
JavaScript
480 lines
15 KiB
JavaScript
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!@#'
|
|
},
|
|
testUser: {
|
|
email: 'usermgmttest@example.com',
|
|
password: 'Test123!@#',
|
|
username: 'usermgmttest'
|
|
}
|
|
};
|
|
|
|
// Test state
|
|
let adminToken = null;
|
|
let regularToken = null;
|
|
let testUserId = 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');
|
|
|
|
// Create test user
|
|
try {
|
|
const registerRes = await axios.post(`${BASE_URL}/auth/register`, testConfig.testUser);
|
|
testUserId = registerRes.data.data.user.id;
|
|
console.log('✓ Test user created');
|
|
} catch (error) {
|
|
if (error.response?.status === 409) {
|
|
// User already exists, login to get ID
|
|
const loginRes = await axios.post(`${BASE_URL}/auth/login`, {
|
|
email: testConfig.testUser.email,
|
|
password: testConfig.testUser.password
|
|
});
|
|
// Get user ID from token or fetch user list
|
|
const usersRes = await axios.get(`${BASE_URL}/admin/users?email=${testConfig.testUser.email}`, {
|
|
headers: { Authorization: `Bearer ${adminToken}` }
|
|
});
|
|
if (usersRes.data.data.users.length > 0) {
|
|
testUserId = usersRes.data.data.users[0].id;
|
|
}
|
|
console.log('✓ Test user already exists');
|
|
}
|
|
}
|
|
|
|
console.log('\n============================================================');
|
|
console.log('USER MANAGEMENT API TESTS');
|
|
console.log('============================================================\n');
|
|
|
|
} catch (error) {
|
|
console.error('Setup failed:', error.response?.data || error.message);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
// Test functions
|
|
async function testGetAllUsers() {
|
|
try {
|
|
const response = await axios.get(`${BASE_URL}/admin/users`, {
|
|
headers: { Authorization: `Bearer ${adminToken}` }
|
|
});
|
|
|
|
const passed = response.status === 200 &&
|
|
response.data.success === true &&
|
|
Array.isArray(response.data.data.users) &&
|
|
response.data.data.pagination !== undefined;
|
|
|
|
logTest('Get all users with pagination', passed);
|
|
return response.data.data;
|
|
} catch (error) {
|
|
logTest('Get all users with pagination', false, error.response?.data?.message || error.message);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function testPaginationStructure(data) {
|
|
if (!data) {
|
|
logTest('Pagination structure validation', false, 'No data available');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const pagination = data.pagination;
|
|
const passed = typeof pagination.currentPage === 'number' &&
|
|
typeof pagination.totalPages === 'number' &&
|
|
typeof pagination.totalItems === 'number' &&
|
|
typeof pagination.itemsPerPage === 'number' &&
|
|
typeof pagination.hasNextPage === 'boolean' &&
|
|
typeof pagination.hasPreviousPage === 'boolean';
|
|
|
|
logTest('Pagination structure validation', passed);
|
|
} catch (error) {
|
|
logTest('Pagination structure validation', false, error.message);
|
|
}
|
|
}
|
|
|
|
async function testUserFieldsStructure(data) {
|
|
if (!data || !data.users || data.users.length === 0) {
|
|
logTest('User fields validation', false, 'No users available');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const user = data.users[0];
|
|
const passed = user.id !== undefined &&
|
|
user.username !== undefined &&
|
|
user.email !== undefined &&
|
|
user.role !== undefined &&
|
|
typeof user.isActive === 'boolean' &&
|
|
user.password === undefined; // Password should be excluded
|
|
|
|
logTest('User fields validation', passed);
|
|
} catch (error) {
|
|
logTest('User fields validation', false, error.message);
|
|
}
|
|
}
|
|
|
|
async function testFilterByRole() {
|
|
try {
|
|
const response = await axios.get(`${BASE_URL}/admin/users?role=user`, {
|
|
headers: { Authorization: `Bearer ${adminToken}` }
|
|
});
|
|
|
|
const passed = response.status === 200 &&
|
|
response.data.data.users.every(u => u.role === 'user');
|
|
|
|
logTest('Filter users by role', passed);
|
|
} catch (error) {
|
|
logTest('Filter users by role', false, error.response?.data?.message || error.message);
|
|
}
|
|
}
|
|
|
|
async function testFilterByActive() {
|
|
try {
|
|
const response = await axios.get(`${BASE_URL}/admin/users?isActive=true`, {
|
|
headers: { Authorization: `Bearer ${adminToken}` }
|
|
});
|
|
|
|
const passed = response.status === 200 &&
|
|
response.data.data.users.every(u => u.isActive === true);
|
|
|
|
logTest('Filter users by isActive', passed);
|
|
} catch (error) {
|
|
logTest('Filter users by isActive', false, error.response?.data?.message || error.message);
|
|
}
|
|
}
|
|
|
|
async function testSorting() {
|
|
try {
|
|
const response = await axios.get(`${BASE_URL}/admin/users?sortBy=username&sortOrder=asc`, {
|
|
headers: { Authorization: `Bearer ${adminToken}` }
|
|
});
|
|
|
|
const passed = response.status === 200 &&
|
|
response.data.data.sorting.sortBy === 'username' &&
|
|
response.data.data.sorting.sortOrder === 'ASC';
|
|
|
|
logTest('Sort users by username', passed);
|
|
} catch (error) {
|
|
logTest('Sort users by username', false, error.response?.data?.message || error.message);
|
|
}
|
|
}
|
|
|
|
async function testGetUserById() {
|
|
if (!testUserId) {
|
|
logTest('Get user by ID', false, 'No test user ID available');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await axios.get(`${BASE_URL}/admin/users/${testUserId}`, {
|
|
headers: { Authorization: `Bearer ${adminToken}` }
|
|
});
|
|
|
|
const passed = response.status === 200 &&
|
|
response.data.success === true &&
|
|
response.data.data.id === testUserId &&
|
|
response.data.data.stats !== undefined &&
|
|
response.data.data.activity !== undefined &&
|
|
Array.isArray(response.data.data.recentSessions);
|
|
|
|
logTest('Get user by ID', passed);
|
|
} catch (error) {
|
|
logTest('Get user by ID', false, error.response?.data?.message || error.message);
|
|
}
|
|
}
|
|
|
|
async function testUpdateUserRole() {
|
|
if (!testUserId) {
|
|
logTest('Update user role', false, 'No test user ID available');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await axios.put(`${BASE_URL}/admin/users/${testUserId}/role`,
|
|
{ role: 'admin' },
|
|
{ headers: { Authorization: `Bearer ${adminToken}` } }
|
|
);
|
|
|
|
const passed = response.status === 200 &&
|
|
response.data.success === true &&
|
|
response.data.data.role === 'admin';
|
|
|
|
logTest('Update user role to admin', passed);
|
|
|
|
// Revert back to user
|
|
if (passed) {
|
|
await axios.put(`${BASE_URL}/admin/users/${testUserId}/role`,
|
|
{ role: 'user' },
|
|
{ headers: { Authorization: `Bearer ${adminToken}` } }
|
|
);
|
|
}
|
|
} catch (error) {
|
|
logTest('Update user role to admin', false, error.response?.data?.message || error.message);
|
|
}
|
|
}
|
|
|
|
async function testPreventLastAdminDemotion() {
|
|
try {
|
|
// Try to demote the admin user (should fail if it's the last admin)
|
|
const usersRes = await axios.get(`${BASE_URL}/admin/users?role=admin`, {
|
|
headers: { Authorization: `Bearer ${adminToken}` }
|
|
});
|
|
|
|
if (usersRes.data.data.users.length <= 1) {
|
|
const adminId = usersRes.data.data.users[0].id;
|
|
|
|
await axios.put(`${BASE_URL}/admin/users/${adminId}/role`,
|
|
{ role: 'user' },
|
|
{ headers: { Authorization: `Bearer ${adminToken}` } }
|
|
);
|
|
|
|
logTest('Prevent demoting last admin', false, 'Should not allow demoting last admin');
|
|
} else {
|
|
logTest('Prevent demoting last admin (skipped - multiple admins)', true);
|
|
}
|
|
} catch (error) {
|
|
const passed = error.response?.status === 400 &&
|
|
error.response?.data?.message?.includes('last admin');
|
|
logTest('Prevent demoting last admin', passed,
|
|
!passed ? `Expected 400 with last admin message, got ${error.response?.status}` : null);
|
|
}
|
|
}
|
|
|
|
async function testDeactivateUser() {
|
|
if (!testUserId) {
|
|
logTest('Deactivate user', false, 'No test user ID available');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await axios.delete(`${BASE_URL}/admin/users/${testUserId}`, {
|
|
headers: { Authorization: `Bearer ${adminToken}` }
|
|
});
|
|
|
|
const passed = response.status === 200 &&
|
|
response.data.success === true &&
|
|
response.data.data.isActive === false;
|
|
|
|
logTest('Deactivate user', passed);
|
|
} catch (error) {
|
|
logTest('Deactivate user', false, error.response?.data?.message || error.message);
|
|
}
|
|
}
|
|
|
|
async function testReactivateUser() {
|
|
if (!testUserId) {
|
|
logTest('Reactivate user', false, 'No test user ID available');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const response = await axios.put(`${BASE_URL}/admin/users/${testUserId}/activate`,
|
|
{},
|
|
{ headers: { Authorization: `Bearer ${adminToken}` } }
|
|
);
|
|
|
|
const passed = response.status === 200 &&
|
|
response.data.success === true &&
|
|
response.data.data.isActive === true;
|
|
|
|
logTest('Reactivate user', passed);
|
|
} catch (error) {
|
|
logTest('Reactivate user', false, error.response?.data?.message || error.message);
|
|
}
|
|
}
|
|
|
|
async function testInvalidUserId() {
|
|
try {
|
|
await axios.get(`${BASE_URL}/admin/users/invalid-uuid`, {
|
|
headers: { Authorization: `Bearer ${adminToken}` }
|
|
});
|
|
logTest('Invalid user ID rejected', false, 'Should reject invalid UUID');
|
|
} catch (error) {
|
|
const passed = error.response?.status === 400;
|
|
logTest('Invalid user ID rejected', passed,
|
|
!passed ? `Expected 400, got ${error.response?.status}` : null);
|
|
}
|
|
}
|
|
|
|
async function testNonExistentUser() {
|
|
try {
|
|
await axios.get(`${BASE_URL}/admin/users/00000000-0000-0000-0000-000000000000`, {
|
|
headers: { Authorization: `Bearer ${adminToken}` }
|
|
});
|
|
logTest('Non-existent user returns 404', false, 'Should return 404');
|
|
} catch (error) {
|
|
const passed = error.response?.status === 404;
|
|
logTest('Non-existent user returns 404', passed,
|
|
!passed ? `Expected 404, got ${error.response?.status}` : null);
|
|
}
|
|
}
|
|
|
|
async function testInvalidRole() {
|
|
if (!testUserId) {
|
|
logTest('Invalid role rejected', false, 'No test user ID available');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await axios.put(`${BASE_URL}/admin/users/${testUserId}/role`,
|
|
{ role: 'superadmin' },
|
|
{ headers: { Authorization: `Bearer ${adminToken}` } }
|
|
);
|
|
logTest('Invalid role rejected', false, 'Should reject invalid role');
|
|
} catch (error) {
|
|
const passed = error.response?.status === 400;
|
|
logTest('Invalid role rejected', passed,
|
|
!passed ? `Expected 400, got ${error.response?.status}` : null);
|
|
}
|
|
}
|
|
|
|
async function testNonAdminBlocked() {
|
|
try {
|
|
await axios.get(`${BASE_URL}/admin/users`, {
|
|
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/users`);
|
|
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');
|
|
|
|
// List users tests
|
|
const data = await testGetAllUsers();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
await testPaginationStructure(data);
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
await testUserFieldsStructure(data);
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
await testFilterByRole();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
await testFilterByActive();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
await testSorting();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
// Get user by ID
|
|
await testGetUserById();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
// Update role tests
|
|
await testUpdateUserRole();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
await testPreventLastAdminDemotion();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
// Deactivate/Reactivate tests
|
|
await testDeactivateUser();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
await testReactivateUser();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
// Validation tests
|
|
await testInvalidUserId();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
await testNonExistentUser();
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
await testInvalidRole();
|
|
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);
|
|
});
|