mcp-banka
Version:
Model Context Protocol Server for Turkish Currency and Exchange Rate data from the Central Bank of The Republic of Turkey (TCMB) (TCMB)
315 lines (314 loc) โข 14.2 kB
JavaScript
import { TcmbApiClient } from './api.js';
async function runTests() {
console.log('๐งช Starting TCMB API Tests...');
console.log('==============================');
const api = new TcmbApiClient();
let testsPassed = 0;
let testsFailed = 0;
// Get real-time XML data for use in later tests
let realXmlData = '';
try {
realXmlData = await api.fetchData();
console.log('โน๏ธ Fetched real-time XML data for testing');
}
catch (error) {
console.error('โ Failed to fetch real-time XML data:', error instanceof Error ? error.message : String(error));
}
// Test 1: URL Generation
try {
const today = new Date();
const url = api.generateUrl(today);
console.log('โ
Test 1: URL Generation:', url);
// Validate URL format
if (url.includes('https://www.tcmb.gov.tr/kurlar/') && url.endsWith('.xml')) {
console.log(' URL validation passed');
testsPassed++;
}
else {
throw new Error('URL format validation failed');
}
}
catch (error) {
console.error('โ Test 1: URL Generation failed:', error instanceof Error ? error.message : String(error));
testsFailed++;
}
console.log('------------------------------');
// Test 2: Fetch XML Data
try {
// We already fetched the XML data above
const xmlData = realXmlData || await api.fetchData();
// Verify it's valid XML by checking for expected tags
if (xmlData.includes('<Tarih_Date') && xmlData.includes('<Currency')) {
console.log('โ
Test 2: Fetch XML Data - Successfully retrieved XML data');
console.log(' XML Sample:', xmlData.substring(0, 100) + '...');
testsPassed++;
}
else {
throw new Error('XML data does not contain expected tags');
}
}
catch (error) {
console.error('โ Test 2: Fetch XML Data failed:', error instanceof Error ? error.message : String(error));
testsFailed++;
}
console.log('------------------------------');
// Test 3: XML to JSON Conversion
try {
const jsonData = await api.fetchDataAsJson();
if (jsonData && jsonData.Tarih_Date && jsonData.Tarih_Date.Currency) {
console.log('โ
Test 3: XML to JSON Conversion - Successfully converted XML to JSON');
console.log(' Date in Response:', jsonData.Tarih_Date['@Date'] || jsonData.Tarih_Date['@Tarih']);
// Check if Currency array exists and has items
const currencies = Array.isArray(jsonData.Tarih_Date.Currency)
? jsonData.Tarih_Date.Currency
: [jsonData.Tarih_Date.Currency];
console.log(` Number of currencies found: ${currencies.length}`);
testsPassed++;
}
else {
throw new Error('JSON data does not contain expected structure');
}
}
catch (error) {
console.error('โ Test 3: XML to JSON Conversion failed:', error instanceof Error ? error.message : String(error));
testsFailed++;
}
console.log('------------------------------');
// Test 4: Get Today's Exchange Rate for USD
try {
const { response, currencyCode } = await api.getTodayExchangeRate('USD');
const currencies = Array.isArray(response.Tarih_Date.Currency)
? response.Tarih_Date.Currency
: [response.Tarih_Date.Currency];
const usdCurrency = currencies.find(c => c['@Kod'] === 'USD');
if (usdCurrency) {
console.log('โ
Test 4: Get Today USD Rate:');
console.log(` USD/TRY Forex Buying: ${usdCurrency.ForexBuying}`);
console.log(` USD/TRY Forex Selling: ${usdCurrency.ForexSelling}`);
testsPassed++;
}
else {
throw new Error('USD currency data not found in response');
}
}
catch (error) {
console.error('โ Test 4: Get Today USD Rate failed:', error instanceof Error ? error.message : String(error));
testsFailed++;
}
console.log('------------------------------');
// Test 5: Get Exchange Rate History
try {
// Try getting EUR rate from a specific date (one week ago)
const pastDate = new Date();
pastDate.setDate(pastDate.getDate() - 7);
const dateString = pastDate.toISOString().split('T')[0]; // YYYY-MM-DD format
const eurHistory = await api.getExchangeRateHistory('EUR', dateString);
if (Array.isArray(eurHistory)) {
console.log(`โ Test 5: Get EUR Rate for ${dateString} - Unexpected array returned`);
testsFailed++;
}
else if (eurHistory.currency === 'EUR') {
console.log(`โ
Test 5: Get EUR Rate for ${dateString}:`);
console.log(` Date: ${eurHistory.date}`);
console.log(` EUR/TRY Forex Buying: ${eurHistory.ForexBuying}`);
console.log(` EUR/TRY Forex Selling: ${eurHistory.ForexSelling}`);
testsPassed++;
}
else {
throw new Error('EUR currency data not found or in unexpected format');
}
}
catch (error) {
console.error('โ Test 5: Get Exchange Rate History failed:', error instanceof Error ? error.message : String(error));
testsFailed++;
}
console.log('------------------------------');
// Test 6: Error Handling - Invalid Currency Code
try {
const invalidResult = await api.getExchangeRateHistory('INVALID', '2023-01-01');
// Since our API returns all currencies when it can't find the specified one
if (Array.isArray(invalidResult)) {
console.log('โ
Test 6: Error Handling - Invalid Currency Code - Successfully handled invalid currency');
console.log(` Returned ${invalidResult.length} currencies as fallback`);
testsPassed++;
}
else {
console.log('โ Test 6: Error Handling - Invalid Currency Code - Unexpected behavior, but no error thrown');
testsPassed += 0.5;
}
}
catch (error) {
console.log('โ
Test 6: Error Handling - Invalid Currency Code - Successfully caught error:', error instanceof Error ? error.message : String(error));
testsPassed++;
}
console.log('------------------------------');
// Test 7: Weekend Date Adjustment
try {
// Create a date for the next Saturday
const saturdayDate = new Date();
while (saturdayDate.getDay() !== 6) {
saturdayDate.setDate(saturdayDate.getDate() + 1);
}
const url = api.generateUrl(saturdayDate);
console.log('โ
Test 7: Weekend Date Adjustment:');
console.log(` Saturday date: ${saturdayDate.toISOString().split('T')[0]}`);
console.log(` Adjusted URL: ${url}`);
// Should contain Friday's date (yesterday)
const fridayDate = new Date(saturdayDate);
fridayDate.setDate(fridayDate.getDate() - 1);
const fridayDateString = `${String(fridayDate.getDate()).padStart(2, '0')}${String(fridayDate.getMonth() + 1).padStart(2, '0')}${fridayDate.getFullYear()}`;
if (url.includes(fridayDateString)) {
console.log(' Date adjustment validation passed (Friday date found in URL)');
testsPassed++;
}
else {
throw new Error('Weekend date adjustment validation failed');
}
}
catch (error) {
console.error('โ Test 7: Weekend Date Adjustment failed:', error instanceof Error ? error.message : String(error));
testsFailed++;
}
console.log('------------------------------');
// NEW TEST 8: Parse today's XML with xmlToJson (test-specific)
try {
// Access the private xmlToJson method through a hack (for testing only)
const anyApi = api;
const jsonData = anyApi.xmlToJson(realXmlData);
// Validate the structure
if (jsonData && jsonData.Tarih_Date) {
console.log('โ
Test 8: Today\'s XML Parsing - Basic structure parsed');
// Validate currencies
const currencies = Array.isArray(jsonData.Tarih_Date.Currency)
? jsonData.Tarih_Date.Currency
: [jsonData.Tarih_Date.Currency];
if (currencies.length >= 1) {
console.log(` Found ${currencies.length} currencies in today\'s XML`);
const usdCurrency = currencies.find((c) => c['@Kod'] === 'USD');
if (usdCurrency) {
console.log(` USD currency found with ForexBuying: ${usdCurrency.ForexBuying}`);
testsPassed++;
}
else {
throw new Error('USD currency not found in parsed XML');
}
}
else {
throw new Error(`No currencies found in parsed XML`);
}
}
else {
throw new Error('Today\'s XML was not parsed correctly');
}
}
catch (error) {
console.error('โ Test 8: Today\'s XML Parsing failed:', error instanceof Error ? error.message : String(error));
testsFailed++;
}
console.log('------------------------------');
// NEW TEST 9: Parse today's XML and verify specific currency values
try {
// Access the private xmlToJson method through a hack (for testing only)
const anyApi = api;
const jsonData = anyApi.xmlToJson(realXmlData);
// Find the EUR currency in the parsed data
const currencies = Array.isArray(jsonData.Tarih_Date.Currency)
? jsonData.Tarih_Date.Currency
: [jsonData.Tarih_Date.Currency];
const eurCurrency = currencies.find((c) => c['@Kod'] === 'EUR');
if (eurCurrency) {
console.log('โ
Test 9: Today\'s Currency Values - Found EUR currency');
// Verify key values are present (not specific values as they change daily)
if (eurCurrency['@Kod'] === 'EUR' &&
eurCurrency.ForexBuying &&
eurCurrency.ForexSelling) {
console.log(' Key EUR currency values verified:');
console.log(` - Kod: ${eurCurrency['@Kod']}`);
console.log(` - ForexBuying: ${eurCurrency.ForexBuying}`);
console.log(` - ForexSelling: ${eurCurrency.ForexSelling}`);
testsPassed++;
}
else {
throw new Error('Key EUR values missing from today\'s data');
}
}
else {
throw new Error('EUR currency not found in today\'s XML parsing result');
}
}
catch (error) {
console.error('โ Test 9: Today\'s Currency Values failed:', error instanceof Error ? error.message : String(error));
testsFailed++;
}
console.log('------------------------------');
// NEW TEST 10: Test extractCurrencyData with today's XML
try {
// Access the private methods through a hack (for testing only)
const anyApi = api;
const jsonData = anyApi.xmlToJson(realXmlData);
// Use the extractCurrencyData method to get GBP data
const gbpData = anyApi.extractCurrencyData(jsonData, 'GBP');
if (gbpData && gbpData.currency === 'GBP') {
console.log('โ
Test 10: Extract Specific Currency - GBP data extracted');
// Verify GBP values are present (not specific values as they change daily)
if (gbpData.ForexBuying &&
gbpData.ForexSelling) {
console.log(' GBP values correctly extracted:');
console.log(` - ForexBuying: ${gbpData.ForexBuying}`);
console.log(` - ForexSelling: ${gbpData.ForexSelling}`);
if (gbpData.CrossRateOther) {
console.log(` - CrossRateOther: ${gbpData.CrossRateOther}`);
}
testsPassed++;
}
else {
throw new Error('GBP data missing key values');
}
}
else {
throw new Error('Failed to extract GBP currency data');
}
}
catch (error) {
console.error('โ Test 10: Extract Specific Currency failed:', error instanceof Error ? error.message : String(error));
testsFailed++;
}
console.log('------------------------------');
// NEW TEST 11: Test missing currency with today's XML
try {
// Access the private methods through a hack (for testing only)
const anyApi = api;
const jsonData = anyApi.xmlToJson(realXmlData);
// Try to extract a currency that doesn't exist
const nonExistentCurrency = 'INVALID_CURRENCY';
const invalidData = anyApi.extractCurrencyData(jsonData, nonExistentCurrency);
// Our implementation should return all currencies when the requested one isn't found
if (Array.isArray(invalidData)) {
console.log('โ
Test 11: Missing Currency Handling - Correctly returned all currencies');
console.log(` Number of currencies returned: ${invalidData.length}`);
testsPassed++;
}
else {
throw new Error('Expected an array of all currencies but got a single currency object');
}
}
catch (error) {
console.error('โ Test 11: Missing Currency Handling failed:', error instanceof Error ? error.message : String(error));
testsFailed++;
}
console.log('==============================');
// Show test results
console.log(`Tests passed: ${testsPassed} | Tests failed: ${testsFailed}`);
console.log(`Test success rate: ${Math.round((testsPassed / (testsPassed + testsFailed)) * 100)}%`);
if (testsFailed === 0) {
console.log('๐ All tests passed!');
}
else {
console.error(`โ ๏ธ ${testsFailed} test(s) failed!`);
}
}
// Run all tests
console.log('Running tests for TcmbApiClient...');
runTests().catch(error => {
console.error('โ Test execution failed:', error instanceof Error ? error.message : String(error));
});