n8n_node_librebooking/test-api.ts

610 lines
18 KiB
TypeScript

/**
* LibreBooking API Test Script
*
* Testet alle wichtigen API-Endpunkte mit echten Credentials
*/
import * as https from 'https';
import * as http from 'http';
const BASE_URL = 'https://librebooking.zell-cloud.de';
const USERNAME = 'sebastian.zell@zell-aufmass.de';
const PASSWORD = 'wanUQ4uVqU6lfP';
interface Session {
sessionToken: string;
userId: number;
}
interface TestResult {
name: string;
success: boolean;
data?: any;
error?: string;
}
const results: TestResult[] = [];
/**
* HTTP Request Helper
*/
function makeRequest(
method: string,
path: string,
body?: any,
session?: Session,
qs?: Record<string, string>
): Promise<any> {
return new Promise((resolve, reject) => {
const url = new URL(path, BASE_URL);
if (qs) {
Object.entries(qs).forEach(([key, value]) => {
if (value) url.searchParams.append(key, value);
});
}
const headers: Record<string, string> = {
'Content-Type': 'application/json',
};
if (session) {
headers['X-Booked-SessionToken'] = session.sessionToken;
headers['X-Booked-UserId'] = session.userId.toString();
}
const options = {
method,
hostname: url.hostname,
path: url.pathname + url.search,
headers,
};
const httpModule = url.protocol === 'https:' ? https : http;
const req = httpModule.request(options, (res) => {
let data = '';
res.on('data', (chunk) => { data += chunk; });
res.on('end', () => {
try {
if (data) {
resolve(JSON.parse(data));
} else {
resolve({ success: true });
}
} catch (e) {
resolve({ rawData: data });
}
});
});
req.on('error', (error) => {
reject(error);
});
if (body) {
req.write(JSON.stringify(body));
}
req.end();
});
}
/**
* Test Authentication
*/
async function testAuthentication(): Promise<Session> {
console.log('\n=== 1. Testing Authentication ===');
try {
const response = await makeRequest(
'POST',
'/Web/Services/index.php/Authentication/Authenticate',
{ username: USERNAME, password: PASSWORD }
);
if (response.isAuthenticated) {
console.log('✅ Authentication successful');
console.log(` Session Token: ${response.sessionToken.substring(0, 20)}...`);
console.log(` User ID: ${response.userId}`);
console.log(` Session Expires: ${response.sessionExpires}`);
results.push({ name: 'Authentication', success: true, data: { userId: response.userId } });
return { sessionToken: response.sessionToken, userId: response.userId };
} else {
throw new Error('Authentication failed');
}
} catch (error: any) {
console.log('❌ Authentication failed:', error.message);
results.push({ name: 'Authentication', success: false, error: error.message });
throw error;
}
}
/**
* Test Get Reservations
*/
async function testGetReservations(session: Session): Promise<void> {
console.log('\n=== 2. Testing Get Reservations ===');
try {
// Test without date filters (should return next 2 weeks)
const response = await makeRequest(
'GET',
'/Web/Services/index.php/Reservations/',
undefined,
session
);
console.log(`✅ Reservations fetched: ${response.reservations?.length || 0} found`);
if (response.reservations && response.reservations.length > 0) {
const res = response.reservations[0];
console.log(` Example: ${res.title || 'No title'} (${res.referenceNumber})`);
console.log(` Start: ${res.startDate}`);
console.log(` Resource: ${res.resourceName}`);
}
results.push({ name: 'Get Reservations (no filter)', success: true, data: { count: response.reservations?.length || 0 } });
// Test with date filter (Feb 7-14, 2026)
console.log('\n Testing with date filter (2026-02-07 to 2026-02-14)...');
const responseFiltered = await makeRequest(
'GET',
'/Web/Services/index.php/Reservations/',
undefined,
session,
{
startDateTime: '2026-02-07T00:00:00',
endDateTime: '2026-02-14T23:59:59'
}
);
console.log(`✅ Filtered reservations: ${responseFiltered.reservations?.length || 0} found`);
results.push({ name: 'Get Reservations (date filter)', success: true, data: { count: responseFiltered.reservations?.length || 0 } });
} catch (error: any) {
console.log('❌ Get Reservations failed:', error.message);
results.push({ name: 'Get Reservations', success: false, error: error.message });
}
}
/**
* Test Get Resources
*/
async function testGetResources(session: Session): Promise<number | null> {
console.log('\n=== 3. Testing Get Resources ===');
try {
const response = await makeRequest(
'GET',
'/Web/Services/index.php/Resources/',
undefined,
session
);
console.log(`✅ Resources fetched: ${response.resources?.length || 0} found`);
let firstResourceId: number | null = null;
if (response.resources && response.resources.length > 0) {
const res = response.resources[0];
firstResourceId = res.resourceId;
console.log(` Example: ${res.name} (ID: ${res.resourceId})`);
console.log(` Schedule ID: ${res.scheduleId}`);
console.log(` Custom Attributes: ${res.customAttributes?.length || 0}`);
if (res.customAttributes && res.customAttributes.length > 0) {
res.customAttributes.forEach((attr: any) => {
console.log(` - ${attr.label}: ${attr.value || '(no value)'}`);
});
}
}
results.push({ name: 'Get Resources', success: true, data: { count: response.resources?.length || 0 } });
return firstResourceId;
} catch (error: any) {
console.log('❌ Get Resources failed:', error.message);
results.push({ name: 'Get Resources', success: false, error: error.message });
return null;
}
}
/**
* Test Get Single Resource (with custom attributes)
*/
async function testGetSingleResource(session: Session, resourceId: number): Promise<void> {
console.log('\n=== 4. Testing Get Single Resource (with custom attributes) ===');
try {
const response = await makeRequest(
'GET',
`/Web/Services/index.php/Resources/${resourceId}`,
undefined,
session
);
console.log(`✅ Resource fetched: ${response.name}`);
console.log(` Custom Attributes: ${response.customAttributes?.length || 0}`);
if (response.customAttributes && response.customAttributes.length > 0) {
response.customAttributes.forEach((attr: any) => {
console.log(` - ID: ${attr.id}, Label: ${attr.label}, Value: ${attr.value || '(no value)'}`);
});
}
results.push({ name: 'Get Single Resource', success: true, data: { customAttributes: response.customAttributes?.length || 0 } });
} catch (error: any) {
console.log('❌ Get Single Resource failed:', error.message);
results.push({ name: 'Get Single Resource', success: false, error: error.message });
}
}
/**
* Test Get Users
*/
async function testGetUsers(session: Session): Promise<number | null> {
console.log('\n=== 5. Testing Get Users ===');
try {
const response = await makeRequest(
'GET',
'/Web/Services/index.php/Users/',
undefined,
session
);
console.log(`✅ Users fetched: ${response.users?.length || 0} found`);
let firstUserId: number | null = null;
if (response.users && response.users.length > 0) {
const user = response.users[0];
firstUserId = user.id;
console.log(` Example: ${user.firstName} ${user.lastName} (ID: ${user.id})`);
}
results.push({ name: 'Get Users', success: true, data: { count: response.users?.length || 0 } });
return firstUserId;
} catch (error: any) {
console.log('❌ Get Users failed:', error.message);
results.push({ name: 'Get Users', success: false, error: error.message });
return null;
}
}
/**
* Test Get Single User (with custom attributes)
*/
async function testGetSingleUser(session: Session, userId: number): Promise<void> {
console.log('\n=== 6. Testing Get Single User (with custom attributes) ===');
try {
const response = await makeRequest(
'GET',
`/Web/Services/index.php/Users/${userId}`,
undefined,
session
);
console.log(`✅ User fetched: ${response.firstName} ${response.lastName}`);
console.log(` Custom Attributes: ${response.customAttributes?.length || 0}`);
if (response.customAttributes && response.customAttributes.length > 0) {
response.customAttributes.forEach((attr: any) => {
console.log(` - ID: ${attr.id}, Label: ${attr.label}, Value: ${attr.value || '(no value)'}`);
});
}
results.push({ name: 'Get Single User', success: true, data: { customAttributes: response.customAttributes?.length || 0 } });
} catch (error: any) {
console.log('❌ Get Single User failed:', error.message);
results.push({ name: 'Get Single User', success: false, error: error.message });
}
}
/**
* Test Get Schedules
*/
async function testGetSchedules(session: Session): Promise<void> {
console.log('\n=== 7. Testing Get Schedules ===');
try {
const response = await makeRequest(
'GET',
'/Web/Services/index.php/Schedules/',
undefined,
session
);
console.log(`✅ Schedules fetched: ${response.schedules?.length || 0} found`);
if (response.schedules && response.schedules.length > 0) {
const schedule = response.schedules[0];
console.log(` Example: ${schedule.name} (ID: ${schedule.id})`);
}
results.push({ name: 'Get Schedules', success: true, data: { count: response.schedules?.length || 0 } });
} catch (error: any) {
console.log('❌ Get Schedules failed:', error.message);
results.push({ name: 'Get Schedules', success: false, error: error.message });
}
}
/**
* Test Get Attributes by Category
*/
async function testGetAttributes(session: Session): Promise<void> {
console.log('\n=== 8. Testing Get Attributes by Category ===');
const categories = [
{ id: 1, name: 'Reservation' },
{ id: 2, name: 'User' },
{ id: 4, name: 'Resource' },
{ id: 5, name: 'Resource Type' },
];
for (const cat of categories) {
try {
const response = await makeRequest(
'GET',
`/Web/Services/index.php/Attributes/Category/${cat.id}`,
undefined,
session
);
console.log(`${cat.name} Attributes: ${response.attributes?.length || 0} found`);
if (response.attributes && response.attributes.length > 0) {
response.attributes.forEach((attr: any) => {
console.log(` - ID: ${attr.id}, Label: ${attr.label}, Type: ${attr.type}, Required: ${attr.required}`);
});
}
results.push({ name: `Get Attributes (${cat.name})`, success: true, data: { count: response.attributes?.length || 0 } });
} catch (error: any) {
console.log(`❌ Get ${cat.name} Attributes failed:`, error.message);
results.push({ name: `Get Attributes (${cat.name})`, success: false, error: error.message });
}
}
}
/**
* Test Create, Update, Delete Reservation
*/
async function testReservationCRUD(session: Session, resourceId: number): Promise<void> {
console.log('\n=== 9. Testing Reservation CRUD ===');
// Create
console.log(' Creating test reservation...');
try {
const createResponse = await makeRequest(
'POST',
'/Web/Services/index.php/Reservations/',
{
title: 'API Test Reservation',
description: 'Created by n8n node test script',
resourceId: resourceId,
startDateTime: '2026-02-07T10:00:00',
endDateTime: '2026-02-07T11:00:00',
userId: session.userId,
termsAccepted: true,
allowParticipation: false,
},
session
);
if (createResponse.referenceNumber) {
console.log(`✅ Reservation created: ${createResponse.referenceNumber}`);
results.push({ name: 'Create Reservation', success: true, data: { referenceNumber: createResponse.referenceNumber } });
const refNum = createResponse.referenceNumber;
// Get the created reservation
console.log(' Fetching created reservation...');
const getResponse = await makeRequest(
'GET',
`/Web/Services/index.php/Reservations/${refNum}`,
undefined,
session
);
console.log(`✅ Reservation fetched: ${getResponse.title}`);
console.log(` Custom Attributes: ${getResponse.customAttributes?.length || 0}`);
if (getResponse.customAttributes && getResponse.customAttributes.length > 0) {
getResponse.customAttributes.forEach((attr: any) => {
console.log(` - ID: ${attr.id}, Label: ${attr.label}, Value: ${attr.value || '(no value)'}`);
});
}
results.push({ name: 'Get Created Reservation', success: true });
// Update
console.log(' Updating reservation...');
const updateResponse = await makeRequest(
'POST',
`/Web/Services/index.php/Reservations/${refNum}?updateScope=this`,
{
title: 'API Test Reservation UPDATED',
description: 'Updated by n8n node test script',
resourceId: resourceId,
startDateTime: '2026-02-07T10:00:00',
endDateTime: '2026-02-07T12:00:00',
termsAccepted: true,
allowParticipation: false,
},
session
);
console.log(`✅ Reservation updated`);
results.push({ name: 'Update Reservation', success: true });
// Delete
console.log(' Deleting reservation...');
const deleteResponse = await makeRequest(
'DELETE',
`/Web/Services/index.php/Reservations/${refNum}?updateScope=this`,
undefined,
session
);
console.log(`✅ Reservation deleted`);
results.push({ name: 'Delete Reservation', success: true });
} else {
console.log('❌ Create Reservation failed - no reference number returned');
console.log(' Response:', JSON.stringify(createResponse, null, 2));
results.push({ name: 'Create Reservation', success: false, error: JSON.stringify(createResponse) });
}
} catch (error: any) {
console.log('❌ Reservation CRUD failed:', error.message);
results.push({ name: 'Reservation CRUD', success: false, error: error.message });
}
}
/**
* Test Groups
*/
async function testGetGroups(session: Session): Promise<void> {
console.log('\n=== 10. Testing Get Groups ===');
try {
const response = await makeRequest(
'GET',
'/Web/Services/index.php/Groups/',
undefined,
session
);
console.log(`✅ Groups fetched: ${response.groups?.length || 0} found`);
if (response.groups && response.groups.length > 0) {
const group = response.groups[0];
console.log(` Example: ${group.name} (ID: ${group.id})`);
}
results.push({ name: 'Get Groups', success: true, data: { count: response.groups?.length || 0 } });
} catch (error: any) {
console.log('❌ Get Groups failed:', error.message);
results.push({ name: 'Get Groups', success: false, error: error.message });
}
}
/**
* Test Accessories
*/
async function testGetAccessories(session: Session): Promise<void> {
console.log('\n=== 11. Testing Get Accessories ===');
try {
const response = await makeRequest(
'GET',
'/Web/Services/index.php/Accessories/',
undefined,
session
);
console.log(`✅ Accessories fetched: ${response.accessories?.length || 0} found`);
if (response.accessories && response.accessories.length > 0) {
const acc = response.accessories[0];
console.log(` Example: ${acc.name} (ID: ${acc.id})`);
}
results.push({ name: 'Get Accessories', success: true, data: { count: response.accessories?.length || 0 } });
} catch (error: any) {
console.log('❌ Get Accessories failed:', error.message);
results.push({ name: 'Get Accessories', success: false, error: error.message });
}
}
/**
* Test SignOut
*/
async function testSignOut(session: Session): Promise<void> {
console.log('\n=== 12. Testing Sign Out ===');
try {
await makeRequest(
'POST',
'/Web/Services/index.php/Authentication/SignOut',
{
userId: session.userId,
sessionToken: session.sessionToken,
}
);
console.log('✅ Sign Out successful');
results.push({ name: 'Sign Out', success: true });
} catch (error: any) {
console.log('❌ Sign Out failed:', error.message);
results.push({ name: 'Sign Out', success: false, error: error.message });
}
}
/**
* Print Summary
*/
function printSummary(): void {
console.log('\n========================================');
console.log(' TEST SUMMARY');
console.log('========================================');
const passed = results.filter(r => r.success).length;
const failed = results.filter(r => !r.success).length;
console.log(`\nTotal Tests: ${results.length}`);
console.log(`✅ Passed: ${passed}`);
console.log(`❌ Failed: ${failed}`);
if (failed > 0) {
console.log('\nFailed Tests:');
results.filter(r => !r.success).forEach(r => {
console.log(` - ${r.name}: ${r.error}`);
});
}
console.log('\n========================================\n');
}
/**
* Main Test Runner
*/
async function runTests(): Promise<void> {
console.log('========================================');
console.log(' LibreBooking API Test Suite');
console.log(` URL: ${BASE_URL}`);
console.log(` User: ${USERNAME}`);
console.log('========================================');
try {
// Authentication
const session = await testAuthentication();
// Get operations
await testGetReservations(session);
const resourceId = await testGetResources(session);
if (resourceId) {
await testGetSingleResource(session, resourceId);
}
const userId = await testGetUsers(session);
if (userId) {
await testGetSingleUser(session, userId);
}
await testGetSchedules(session);
await testGetAttributes(session);
await testGetGroups(session);
await testGetAccessories(session);
// CRUD operations
if (resourceId) {
await testReservationCRUD(session, resourceId);
}
// Sign out
await testSignOut(session);
} catch (error: any) {
console.log('\n❌ Test suite failed:', error.message);
}
printSummary();
}
// Run tests
runTests().catch(console.error);