225 lines
6.9 KiB
JavaScript
225 lines
6.9 KiB
JavaScript
/**
|
||
* Test Auto-Eligibility Filtering in /api/activePromos Endpoint
|
||
*
|
||
* Tests that the activePromos endpoint:
|
||
* 1. Requires authentication
|
||
* 2. Automatically filters promos by customer eligibility
|
||
* 3. Returns only eligible promos based on subscription history
|
||
*
|
||
* Prerequisites:
|
||
* - MongoDB running with test promos configured
|
||
* - Valid test user with authentication token
|
||
* - Subscription history cache populated
|
||
*/
|
||
|
||
const path = require('path');
|
||
|
||
// Parse --env argument (default: ./environment.env)
|
||
const args = process.argv.slice(2);
|
||
let envFile = './environment.env';
|
||
for (let i = 0; i < args.length; i++) {
|
||
if (args[i] === '--env' && args[i + 1]) {
|
||
envFile = args[i + 1];
|
||
i++;
|
||
}
|
||
}
|
||
|
||
// Load environment before requiring any modules
|
||
const envPath = path.resolve(process.cwd(), envFile);
|
||
require('dotenv').config({ path: envPath });
|
||
|
||
const axios = require('axios');
|
||
const assert = require('assert');
|
||
|
||
// Test configuration
|
||
const BASE_URL = process.env.APP_URL || 'https://localhost:4200';
|
||
const API_URL = BASE_URL.replace('4200', '4100'); // Server runs on 4100
|
||
|
||
// Test user credentials (update with valid test user)
|
||
const TEST_USER_EMAIL = 'trungduyhoang@gmail.com';
|
||
const TEST_USER_PASSWORD = 'secret';
|
||
|
||
let authToken = null;
|
||
let testUserId = null;
|
||
|
||
// HTTPS agent to accept self-signed certificates
|
||
const https = require('https');
|
||
const httpsAgent = new https.Agent({
|
||
rejectUnauthorized: false
|
||
});
|
||
|
||
/**
|
||
* Step 1: Login to get authentication token
|
||
*/
|
||
async function login() {
|
||
try {
|
||
console.log('\n--- Step 1: Login ---');
|
||
const response = await axios.post(`${API_URL}/api/users/login`, {
|
||
username: TEST_USER_EMAIL,
|
||
password: TEST_USER_PASSWORD
|
||
}, { httpsAgent });
|
||
|
||
authToken = response.data.token;
|
||
testUserId = response.data.user?._id;
|
||
|
||
console.log('✅ Login successful');
|
||
console.log(` User ID: ${testUserId}`);
|
||
console.log(` Token: ${authToken.substring(0, 20)}...`);
|
||
|
||
return true;
|
||
} catch (error) {
|
||
console.error('❌ Login failed:', error.response?.data || error.message);
|
||
console.error('\n⚠️ Update TEST_USER_EMAIL and TEST_USER_PASSWORD in script with valid credentials');
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Step 2: Test authenticated access to /api/activePromos
|
||
*/
|
||
async function testAuthenticatedAccess() {
|
||
try {
|
||
console.log('\n--- Step 2: Test Authenticated Access ---');
|
||
const response = await axios.get(`${API_URL}/api/activePromos`, {
|
||
headers: {
|
||
'Authorization': `Bearer ${authToken}`
|
||
},
|
||
httpsAgent
|
||
});
|
||
|
||
console.log('✅ Authenticated request successful');
|
||
console.log(` Promos returned: ${response.data.promos.length}`);
|
||
console.log(` Current mode: ${response.data.currentMode.mode}`);
|
||
console.log(` Mode active: ${response.data.currentMode.isActive}`);
|
||
|
||
// Verify response structure
|
||
assert(Array.isArray(response.data.promos), 'promos should be an array');
|
||
assert(response.data.currentMode, 'currentMode should be present');
|
||
assert(['enabled', 'disabled'].includes(response.data.currentMode.mode),
|
||
'currentMode.mode should be "enabled" or "disabled"');
|
||
|
||
return response.data;
|
||
} catch (error) {
|
||
console.error('❌ Authenticated request failed:', error.response?.data || error.message);
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Step 3: Test unauthenticated access (should fail)
|
||
*/
|
||
async function testUnauthenticatedAccess() {
|
||
try {
|
||
console.log('\n--- Step 3: Test Unauthenticated Access (Should Fail) ---');
|
||
await axios.get(`${API_URL}/api/activePromos`, { httpsAgent });
|
||
|
||
console.error('❌ UNEXPECTED: Unauthenticated request succeeded (should have failed)');
|
||
return false;
|
||
} catch (error) {
|
||
if (error.response?.status === 401) {
|
||
console.log('✅ Unauthenticated request correctly rejected (401)');
|
||
return true;
|
||
}
|
||
console.error('❌ Unexpected error:', error.response?.data || error.message);
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Step 4: Verify eligibility filtering
|
||
*/
|
||
async function verifyEligibilityFiltering(promosData) {
|
||
console.log('\n--- Step 4: Verify Eligibility Filtering ---');
|
||
|
||
const promos = promosData.promos;
|
||
|
||
// All returned promos should have eligibility field
|
||
const allHaveEligibility = promos.every(p => p.eligibility);
|
||
assert(allHaveEligibility, 'All promos should have eligibility field');
|
||
console.log('✅ All promos have eligibility field');
|
||
|
||
// Check eligibility values
|
||
const eligibilityTypes = [...new Set(promos.map(p => p.eligibility))];
|
||
console.log(` Eligibility types in results: ${eligibilityTypes.join(', ')}`);
|
||
|
||
// All eligibility values should be valid
|
||
const validEligibility = promos.every(p => ['all', 'new_only', 'renew_only'].includes(p.eligibility));
|
||
assert(validEligibility, 'All eligibility values should be valid');
|
||
console.log('✅ All eligibility values are valid');
|
||
|
||
// Log details
|
||
console.log('\n Promo Details:');
|
||
promos.forEach((p, i) => {
|
||
console.log(` ${i + 1}. ${p.name}`);
|
||
console.log(` Type: ${p.type}, PriceKey: ${p.priceKey}`);
|
||
console.log(` Eligibility: ${p.eligibility}`);
|
||
console.log(` Priority: ${p.priority}`);
|
||
if (p.durationInMonths) {
|
||
console.log(` Duration: ${p.durationInMonths} months`);
|
||
}
|
||
if (p.validUntil) {
|
||
console.log(` Valid Until: ${p.validUntil}`);
|
||
}
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Step 5: Test PROMO_MODE disabled
|
||
*/
|
||
async function testDisabledMode() {
|
||
console.log('\n--- Step 5: Test PROMO_MODE Disabled (Manual) ---');
|
||
console.log('⚠️ To test disabled mode:');
|
||
console.log(' 1. Set PROMO_MODE=disabled in environment.env');
|
||
console.log(' 2. Restart server');
|
||
console.log(' 3. Run this test again');
|
||
console.log(' 4. Expected: promos array should be empty, mode should be "disabled"');
|
||
console.log(' 5. Remember to set PROMO_MODE=enabled after testing');
|
||
}
|
||
|
||
/**
|
||
* Main test execution
|
||
*/
|
||
async function runTests() {
|
||
console.log('='.repeat(70));
|
||
console.log('TEST: Active Promos Auto-Eligibility Filtering');
|
||
console.log('='.repeat(70));
|
||
console.log(`API URL: ${API_URL}`);
|
||
console.log(`Test User: ${TEST_USER_EMAIL}`);
|
||
|
||
try {
|
||
// Step 1: Login
|
||
const loginSuccess = await login();
|
||
if (!loginSuccess) {
|
||
process.exit(1);
|
||
}
|
||
|
||
// Step 2: Test authenticated access
|
||
const promosData = await testAuthenticatedAccess();
|
||
|
||
// Step 3: Test unauthenticated access
|
||
await testUnauthenticatedAccess();
|
||
|
||
// Step 4: Verify eligibility filtering
|
||
await verifyEligibilityFiltering(promosData);
|
||
|
||
// Step 5: Manual test for disabled mode
|
||
await testDisabledMode();
|
||
|
||
console.log('\n' + '='.repeat(70));
|
||
console.log('✅ ALL TESTS PASSED');
|
||
console.log('='.repeat(70));
|
||
|
||
} catch (error) {
|
||
console.error('\n' + '='.repeat(70));
|
||
console.error('❌ TEST FAILED');
|
||
console.error('='.repeat(70));
|
||
console.error(error);
|
||
process.exit(1);
|
||
}
|
||
}
|
||
|
||
// Run tests
|
||
runTests();
|