298 lines
6.3 KiB
JavaScript
298 lines
6.3 KiB
JavaScript
/**
|
|
* Test script for fallback recommendation logic
|
|
*
|
|
* Run with: node test-fallback-recommendations.js
|
|
*/
|
|
|
|
// Simulate the fallback logic from the edge function
|
|
function testFallbackRecommendations(trip) {
|
|
const { totalDays, totalPlaces, totalDistanceKm, totalTimeHours, maxDensityScore, travelers } = trip;
|
|
|
|
// Check if trip is truly trivial
|
|
const isTrivialTrip = totalPlaces <= 1 && totalDistanceKm < 5 && totalTimeHours < 2;
|
|
|
|
if (isTrivialTrip) {
|
|
return {
|
|
recommend: false,
|
|
reason: 'Trip is trivial',
|
|
confidence: 0
|
|
};
|
|
}
|
|
|
|
// Fallback 1: Short but dense trips
|
|
if (totalDays === 1 && maxDensityScore >= 30) {
|
|
if (travelers >= 4) {
|
|
return {
|
|
recommend: true,
|
|
slug: 'private_guide',
|
|
type: 'private_guide',
|
|
confidence: 0.65,
|
|
reason: 'Short dense trip with large group'
|
|
};
|
|
} else {
|
|
return {
|
|
recommend: true,
|
|
slug: 'driver_car',
|
|
type: 'driver_car',
|
|
confidence: 0.60,
|
|
reason: 'Short dense trip'
|
|
};
|
|
}
|
|
}
|
|
|
|
// Fallback 2: Long distances
|
|
if (totalDistanceKm >= 50) {
|
|
return {
|
|
recommend: true,
|
|
slug: 'driver_car',
|
|
type: 'driver_car',
|
|
confidence: 0.65,
|
|
reason: 'Long distance travel'
|
|
};
|
|
}
|
|
|
|
// Fallback 3: Multiple places
|
|
if (totalPlaces >= 3) {
|
|
return {
|
|
recommend: true,
|
|
slug: 'private_guide',
|
|
type: 'private_guide',
|
|
confidence: 0.55,
|
|
reason: 'Multiple destinations'
|
|
};
|
|
}
|
|
|
|
// Fallback 4: Large groups
|
|
if (travelers >= 4) {
|
|
return {
|
|
recommend: true,
|
|
slug: 'private_guide',
|
|
type: 'private_guide',
|
|
confidence: 0.60,
|
|
reason: 'Large group'
|
|
};
|
|
}
|
|
|
|
// No fallback matched - would go to AI
|
|
return {
|
|
recommend: true,
|
|
slug: 'ai_fallback',
|
|
type: 'unknown',
|
|
confidence: 0.40,
|
|
reason: 'AI fallback'
|
|
};
|
|
}
|
|
|
|
// Test cases
|
|
const testCases = [
|
|
{
|
|
name: 'Short Dense Trip (Small Group)',
|
|
trip: {
|
|
totalDays: 1,
|
|
totalPlaces: 5,
|
|
totalDistanceKm: 30,
|
|
totalTimeHours: 6,
|
|
maxDensityScore: 35,
|
|
travelers: 2
|
|
},
|
|
expected: {
|
|
recommend: true,
|
|
slug: 'driver_car',
|
|
confidence: 0.60
|
|
}
|
|
},
|
|
{
|
|
name: 'Short Dense Trip (Large Group)',
|
|
trip: {
|
|
totalDays: 1,
|
|
totalPlaces: 6,
|
|
totalDistanceKm: 25,
|
|
totalTimeHours: 7,
|
|
maxDensityScore: 40,
|
|
travelers: 5
|
|
},
|
|
expected: {
|
|
recommend: true,
|
|
slug: 'private_guide',
|
|
confidence: 0.65
|
|
}
|
|
},
|
|
{
|
|
name: 'Long Distance Trip',
|
|
trip: {
|
|
totalDays: 2,
|
|
totalPlaces: 4,
|
|
totalDistanceKm: 85,
|
|
totalTimeHours: 10,
|
|
maxDensityScore: 25,
|
|
travelers: 3
|
|
},
|
|
expected: {
|
|
recommend: true,
|
|
slug: 'driver_car',
|
|
confidence: 0.65
|
|
}
|
|
},
|
|
{
|
|
name: 'Multiple Places (No Other Triggers)',
|
|
trip: {
|
|
totalDays: 2,
|
|
totalPlaces: 4,
|
|
totalDistanceKm: 30,
|
|
totalTimeHours: 8,
|
|
maxDensityScore: 20,
|
|
travelers: 2
|
|
},
|
|
expected: {
|
|
recommend: true,
|
|
slug: 'private_guide',
|
|
confidence: 0.55
|
|
}
|
|
},
|
|
{
|
|
name: 'Large Group (Small Trip)',
|
|
trip: {
|
|
totalDays: 1,
|
|
totalPlaces: 2,
|
|
totalDistanceKm: 15,
|
|
totalTimeHours: 4,
|
|
maxDensityScore: 15,
|
|
travelers: 5
|
|
},
|
|
expected: {
|
|
recommend: true,
|
|
slug: 'private_guide',
|
|
confidence: 0.60
|
|
}
|
|
},
|
|
{
|
|
name: 'Trivial Trip',
|
|
trip: {
|
|
totalDays: 1,
|
|
totalPlaces: 1,
|
|
totalDistanceKm: 2,
|
|
totalTimeHours: 1,
|
|
maxDensityScore: 5,
|
|
travelers: 2
|
|
},
|
|
expected: {
|
|
recommend: false,
|
|
confidence: 0
|
|
}
|
|
},
|
|
{
|
|
name: 'Edge Case: 1 Day, Low Density, Short Distance',
|
|
trip: {
|
|
totalDays: 1,
|
|
totalPlaces: 2,
|
|
totalDistanceKm: 10,
|
|
totalTimeHours: 3,
|
|
maxDensityScore: 12,
|
|
travelers: 2
|
|
},
|
|
expected: {
|
|
recommend: true,
|
|
slug: 'ai_fallback' // Would go to AI
|
|
}
|
|
},
|
|
{
|
|
name: 'Edge Case: Exactly 50km (Boundary)',
|
|
trip: {
|
|
totalDays: 2,
|
|
totalPlaces: 3,
|
|
totalDistanceKm: 50,
|
|
totalTimeHours: 6,
|
|
maxDensityScore: 18,
|
|
travelers: 2
|
|
},
|
|
expected: {
|
|
recommend: true,
|
|
slug: 'driver_car',
|
|
confidence: 0.65
|
|
}
|
|
},
|
|
{
|
|
name: 'Edge Case: Exactly 30 Density (Boundary)',
|
|
trip: {
|
|
totalDays: 1,
|
|
totalPlaces: 4,
|
|
totalDistanceKm: 20,
|
|
totalTimeHours: 5,
|
|
maxDensityScore: 30,
|
|
travelers: 2
|
|
},
|
|
expected: {
|
|
recommend: true,
|
|
slug: 'driver_car',
|
|
confidence: 0.60
|
|
}
|
|
},
|
|
{
|
|
name: 'Edge Case: Exactly 4 Travelers (Boundary)',
|
|
trip: {
|
|
totalDays: 1,
|
|
totalPlaces: 2,
|
|
totalDistanceKm: 10,
|
|
totalTimeHours: 3,
|
|
maxDensityScore: 10,
|
|
travelers: 4
|
|
},
|
|
expected: {
|
|
recommend: true,
|
|
slug: 'private_guide',
|
|
confidence: 0.60
|
|
}
|
|
}
|
|
];
|
|
|
|
// Run tests
|
|
console.log('🧪 Testing Fallback Recommendation Logic\n');
|
|
|
|
let passed = 0;
|
|
let failed = 0;
|
|
|
|
testCases.forEach((test) => {
|
|
const result = testFallbackRecommendations(test.trip);
|
|
|
|
let success = true;
|
|
let errors = [];
|
|
|
|
if (result.recommend !== test.expected.recommend) {
|
|
success = false;
|
|
errors.push(`recommend: ${result.recommend} (expected: ${test.expected.recommend})`);
|
|
}
|
|
|
|
if (test.expected.slug && result.slug !== test.expected.slug) {
|
|
success = false;
|
|
errors.push(`slug: ${result.slug} (expected: ${test.expected.slug})`);
|
|
}
|
|
|
|
if (test.expected.confidence !== undefined && result.confidence !== test.expected.confidence) {
|
|
success = false;
|
|
errors.push(`confidence: ${result.confidence} (expected: ${test.expected.confidence})`);
|
|
}
|
|
|
|
if (success) {
|
|
console.log(`✅ ${test.name}`);
|
|
console.log(` → ${result.slug} (confidence: ${result.confidence})`);
|
|
passed++;
|
|
} else {
|
|
console.log(`❌ ${test.name}`);
|
|
console.log(` → Got: ${result.slug} (confidence: ${result.confidence})`);
|
|
console.log(` → Expected: ${test.expected.slug} (confidence: ${test.expected.confidence})`);
|
|
errors.forEach(err => console.log(` → Error: ${err}`));
|
|
failed++;
|
|
}
|
|
console.log('');
|
|
});
|
|
|
|
console.log(`📊 Results: ${passed} passed, ${failed} failed`);
|
|
|
|
if (failed === 0) {
|
|
console.log('🎉 All tests passed!');
|
|
process.exit(0);
|
|
} else {
|
|
console.log('❌ Some tests failed!');
|
|
process.exit(1);
|
|
}
|