Skip to main content
Glama
test-slug-config.tsโ€ข7.11 kB
#!/usr/bin/env tsx /** * Test script for slug-based environment configuration * This script tests the new slug-based environment discovery system */ import { loadConfigFromEnvOnly } from "../src/config.js"; // Test data - mock environment variables const testCases = [ { name: "Multi-instance slug-based configuration", env: { SONARR_MAIN_URL: "http://sonarr-main:8989", SONARR_MAIN_API_KEY: "sonarr-main-key", SONARR_4K_URL: "http://sonarr-4k:8989", SONARR_4K_API_KEY: "sonarr-4k-key", SONARR_ANIME_URL: "http://sonarr-anime:8989", SONARR_ANIME_API_KEY: "sonarr-anime-key", SONARR_ANIME_NAME: "sonarr-anime-special", RADARR_MAIN_URL: "http://radarr-main:7878", RADARR_MAIN_API_KEY: "radarr-main-key", RADARR_UHD_URL: "http://radarr-uhd:7878", RADARR_UHD_API_KEY: "radarr-uhd-key", SABNZBD_MAIN_URL: "http://sab-main:8080", SABNZBD_MAIN_API_KEY: "sab-main-key", SABNZBD_4K_URL: "http://sab-4k:8080", SABNZBD_4K_API_KEY: "sab-4k-key", }, expectedServices: [ "sonarr-main", "sonarr-4k", "sonarr-anime-special", "radarr-main", "radarr-uhd" ], expectedDownloaders: [ "sabnzbd-main", "sabnzbd-4k" ] }, { name: "Single instance fallback configuration", env: { SONARR_URL: "http://localhost:8989", SONARR_API_KEY: "sonarr-key", RADARR_URL: "http://localhost:7878", RADARR_API_KEY: "radarr-key", SABNZBD_URL: "http://localhost:8080", SABNZBD_API_KEY: "sabnzbd-key" }, expectedServices: [ "sonarr", "radarr" ], expectedDownloaders: [ "sabnzbd" ] }, { name: "Mixed valid and incomplete slugs", env: { SONARR_MAIN_URL: "http://sonarr-main:8989", SONARR_MAIN_API_KEY: "sonarr-main-key", SONARR_INCOMPLETE_URL: "http://sonarr-incomplete:8989", // Missing SONARR_INCOMPLETE_API_KEY RADARR_VALID_URL: "http://radarr-valid:7878", RADARR_VALID_API_KEY: "radarr-valid-key", RADARR_ALSO_INCOMPLETE_API_KEY: "some-key", // Missing RADARR_ALSO_INCOMPLETE_URL }, expectedServices: [ "sonarr-main", "radarr-valid" ], expectedDownloaders: [] }, { name: "URL normalization test", env: { SONARR_TEST_URL: "http://localhost:8989/", SONARR_TEST_API_KEY: "test-key", }, expectedServices: [ "sonarr-test" ], expectedDownloaders: [] }, { name: "No configuration", env: {}, shouldFail: true } ]; function mockEnv(env: Record<string, string>) { // Clear existing relevant env vars for (const key of Object.keys(process.env)) { if (key.startsWith('SONARR_') || key.startsWith('RADARR_') || key.startsWith('SABNZBD_')) { delete process.env[key]; } } // Set test env vars Object.assign(process.env, env); } function restoreEnv() { // Clear test env vars for (const key of Object.keys(process.env)) { if (key.startsWith('SONARR_') || key.startsWith('RADARR_') || key.startsWith('SABNZBD_')) { delete process.env[key]; } } } async function runTest(testCase: typeof testCases[0]) { console.log(`\n๐Ÿงช Testing: ${testCase.name}`); console.log("=" + "=".repeat(testCase.name.length + 10)); try { // Mock environment mockEnv(testCase.env); // Enable debug for testing process.env.FLIX_BRIDGE_DEBUG = "1"; if (testCase.shouldFail) { try { await loadConfigFromEnvOnly(); console.log("โŒ Expected test to fail but it succeeded"); return false; } catch (error) { console.log("โœ… Test correctly failed with expected error"); console.log(` Error: ${error instanceof Error ? error.message : error}`); return true; } } const config = await loadConfigFromEnvOnly(); // Validate services const actualServices = Object.keys(config.services).sort(); const expectedServices = testCase.expectedServices?.sort() || []; console.log(`๐Ÿ“‹ Expected services: [${expectedServices.join(", ")}]`); console.log(`๐Ÿ“‹ Actual services: [${actualServices.join(", ")}]`); if (JSON.stringify(actualServices) !== JSON.stringify(expectedServices)) { console.log("โŒ Service names mismatch"); return false; } // Validate downloaders const actualDownloaders = Object.keys(config.downloaders || {}).sort(); const expectedDownloaders = testCase.expectedDownloaders?.sort() || []; console.log(`๐Ÿ“ฅ Expected downloaders: [${expectedDownloaders.join(", ")}]`); console.log(`๐Ÿ“ฅ Actual downloaders: [${actualDownloaders.join(", ")}]`); if (JSON.stringify(actualDownloaders) !== JSON.stringify(expectedDownloaders)) { console.log("โŒ Downloader names mismatch"); return false; } // Validate service configurations for (const [serviceName, serviceConfig] of Object.entries(config.services)) { if (!serviceConfig.baseUrl || !serviceConfig.apiKey) { console.log(`โŒ Service ${serviceName} missing baseUrl or apiKey`); return false; } // Check URL normalization if (serviceConfig.baseUrl.endsWith('/')) { console.log(`โŒ Service ${serviceName} URL not normalized (ends with /)`); return false; } } // Validate downloader configurations for (const [downloaderName, downloaderConfig] of Object.entries(config.downloaders || {})) { if (!downloaderConfig.baseUrl || !downloaderConfig.apiKey) { console.log(`โŒ Downloader ${downloaderName} missing baseUrl or apiKey`); return false; } if (!downloaderConfig.name) { console.log(`โŒ Downloader ${downloaderName} missing name`); return false; } } console.log("โœ… All validations passed"); return true; } catch (error) { console.log("โŒ Test failed with error:"); console.log(` ${error instanceof Error ? error.message : error}`); return false; } finally { restoreEnv(); } } async function main() { console.log("๐Ÿš€ FlixBridge Slug-Based Configuration Test Suite"); console.log("================================================"); let passed = 0; let failed = 0; for (const testCase of testCases) { const success = await runTest(testCase); if (success) { passed++; } else { failed++; } } console.log("\n" + "=".repeat(50)); console.log("๐Ÿ“Š Test Results Summary"); console.log("=".repeat(50)); console.log(`โœ… Passed: ${passed}`); console.log(`โŒ Failed: ${failed}`); console.log(`๐Ÿ“ˆ Total: ${passed + failed}`); if (failed === 0) { console.log("\n๐ŸŽ‰ All tests passed! Slug-based configuration is working correctly."); process.exit(0); } else { console.log(`\n๐Ÿ’ฅ ${failed} test(s) failed. Please check the implementation.`); process.exit(1); } } if (import.meta.url === `file://${process.argv[1]}`) { main().catch((error) => { console.error("๐Ÿ’ฅ Test suite failed to run:", error); process.exit(1); }); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/thesammykins/FlixBridge'

If you have feedback or need assistance with the MCP directory API, please join our Discord server