#!/usr/bin/env node /** * πŸ”₯ λ²„νŠΌ μ œμ–΄κ΄€λ¦¬ κΈ°λŠ₯ μˆ˜λ™ ν…ŒμŠ€νŠΈ 슀크립트 * * Jestκ°€ μ—†λŠ” ν™˜κ²½μ—μ„œ 기본적인 κΈ°λŠ₯듀을 κ²€μ¦ν•©λ‹ˆλ‹€. */ const axios = require("axios"); // μ„€μ • const BACKEND_URL = "http://localhost:8080"; const FRONTEND_URL = "http://localhost:3000"; // ν…ŒμŠ€νŠΈ 데이터 const mockButtonConfig = { actionType: "save", enableDataflowControl: true, dataflowTiming: "after", dataflowConfig: { controlMode: "simple", selectedDiagramId: 1, selectedRelationshipId: "rel-123", }, }; const mockContextData = { testField: "test-value", status: "active", userId: "test-user", }; // ν…ŒμŠ€νŠΈ κ²°κ³Ό μ €μž₯ let testResults = []; // μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜λ“€ function log(message, type = "info") { const timestamp = new Date().toISOString(); const prefix = { info: "πŸ“‹", success: "βœ…", error: "❌", warning: "⚠️", performance: "⚑", }[type]; console.log(`${prefix} [${timestamp}] ${message}`); } function measureTime(name, fn) { return new Promise(async (resolve, reject) => { const startTime = performance.now(); try { const result = await fn(); const endTime = performance.now(); const duration = endTime - startTime; testResults.push({ name, duration, success: true, result, }); log(`${name}: ${duration.toFixed(2)}ms`, "performance"); resolve({ result, duration }); } catch (error) { const endTime = performance.now(); const duration = endTime - startTime; testResults.push({ name, duration, success: false, error: error.message, }); log( `${name} FAILED: ${error.message} (${duration.toFixed(2)}ms)`, "error" ); reject(error); } }); } // ν…ŒμŠ€νŠΈ ν•¨μˆ˜λ“€ async function testBackendHealthCheck() { try { const response = await axios.get(`${BACKEND_URL}/health`); log("λ°±μ—”λ“œ μ„œλ²„ μƒνƒœ: 정상", "success"); return response.data; } catch (error) { log("λ°±μ—”λ“œ μ„œλ²„ μ—°κ²° μ‹€νŒ¨", "error"); throw error; } } async function testFrontendHealthCheck() { try { const response = await axios.get(`${FRONTEND_URL}`); log("ν”„λ‘ νŠΈμ—”λ“œ μ„œλ²„ μƒνƒœ: 정상", "success"); return { status: "ok" }; } catch (error) { log("ν”„λ‘ νŠΈμ—”λ“œ μ„œλ²„ μ—°κ²° μ‹€νŒ¨", "error"); throw error; } } async function testTestModeStatus() { try { const response = await axios.get( `${BACKEND_URL}/api/test-button-dataflow/test-status` ); log("ν…ŒμŠ€νŠΈ λͺ¨λ“œ μƒνƒœ: 정상", "success"); return response.data; } catch (error) { log(`ν…ŒμŠ€νŠΈ λͺ¨λ“œ 확인 μ‹€νŒ¨: ${error.message}`, "error"); throw error; } } async function testButtonDataflowConfig() { try { const response = await axios.get( `${BACKEND_URL}/api/test-button-dataflow/config/test-button-1` ); log("λ²„νŠΌ μ„€μ • 쑰회: 성곡", "success"); return response.data; } catch (error) { log(`λ²„νŠΌ μ„€μ • 쑰회 μ‹€νŒ¨: ${error.message}`, "error"); throw error; } } async function testDataflowDiagrams() { try { const response = await axios.get( `${BACKEND_URL}/api/test-button-dataflow/diagrams` ); log("관계도 λͺ©λ‘ 쑰회: 성곡", "success"); return response.data; } catch (error) { log(`관계도 λͺ©λ‘ 쑰회 μ‹€νŒ¨: ${error.message}`, "error"); throw error; } } async function testOptimizedExecution() { try { const response = await axios.post( `${BACKEND_URL}/api/test-button-dataflow/execute-optimized`, { buttonId: "test-button-optimized", actionType: "save", buttonConfig: mockButtonConfig, contextData: mockContextData, companyCode: "DEFAULT", } ); log("μ΅œμ ν™”λœ μ‹€ν–‰: 성곡", "success"); return response.data; } catch (error) { log(`μ΅œμ ν™”λœ μ‹€ν–‰ μ‹€νŒ¨: ${error.message}`, "error"); throw error; } } async function testPerformanceLoad() { const requests = 10; const promises = []; log(`μ„±λŠ₯ λΆ€ν•˜ ν…ŒμŠ€νŠΈ μ‹œμž‘ (${requests}개 μš”μ²­)`, "info"); for (let i = 0; i < requests; i++) { promises.push( axios.post(`${BACKEND_URL}/api/test-button-dataflow/execute-optimized`, { buttonId: `load-test-button-${i}`, actionType: "save", buttonConfig: mockButtonConfig, contextData: { ...mockContextData, index: i }, companyCode: "DEFAULT", }) ); } const responses = await Promise.allSettled(promises); const successful = responses.filter((r) => r.status === "fulfilled").length; const failed = responses.filter((r) => r.status === "rejected").length; log( `λΆ€ν•˜ ν…ŒμŠ€νŠΈ μ™„λ£Œ: 성곡 ${successful}개, μ‹€νŒ¨ ${failed}개`, failed === 0 ? "success" : "warning" ); return { successful, failed, total: requests }; } // 메인 ν…ŒμŠ€νŠΈ μ‹€ν–‰ async function runAllTests() { log("πŸ”₯ λ²„νŠΌ μ œμ–΄κ΄€λ¦¬ κΈ°λŠ₯ ν…ŒμŠ€νŠΈ μ‹œμž‘", "info"); log("=".repeat(50), "info"); const tests = [ { name: "λ°±μ—”λ“œ μ„œλ²„ μƒνƒœ 확인", fn: testBackendHealthCheck }, { name: "ν”„λ‘ νŠΈμ—”λ“œ μ„œλ²„ μƒνƒœ 확인", fn: testFrontendHealthCheck }, { name: "ν…ŒμŠ€νŠΈ λͺ¨λ“œ μƒνƒœ 확인", fn: testTestModeStatus }, { name: "λ²„νŠΌ μ„€μ • 쑰회 ν…ŒμŠ€νŠΈ", fn: testButtonDataflowConfig }, { name: "관계도 λͺ©λ‘ 쑰회 ν…ŒμŠ€νŠΈ", fn: testDataflowDiagrams }, { name: "μ΅œμ ν™”λœ μ‹€ν–‰ ν…ŒμŠ€νŠΈ", fn: testOptimizedExecution }, { name: "μ„±λŠ₯ λΆ€ν•˜ ν…ŒμŠ€νŠΈ", fn: testPerformanceLoad }, ]; let passed = 0; let failed = 0; for (const test of tests) { try { await measureTime(test.name, test.fn); passed++; } catch (error) { failed++; // ν…ŒμŠ€νŠΈ μ‹€νŒ¨ν•΄λ„ 계속 μ§„ν–‰ } // 각 ν…ŒμŠ€νŠΈ 사이에 μž μ‹œ λŒ€κΈ° await new Promise((resolve) => setTimeout(resolve, 100)); } // κ²°κ³Ό μš”μ•½ log("=".repeat(50), "info"); log("πŸ“Š ν…ŒμŠ€νŠΈ κ²°κ³Ό μš”μ•½", "info"); log(`총 ν…ŒμŠ€νŠΈ: ${tests.length}개`, "info"); log(`성곡: ${passed}개`, "success"); log(`μ‹€νŒ¨: ${failed}개`, failed > 0 ? "error" : "success"); // μ„±λŠ₯ λ©”νŠΈλ¦­ const successfulTests = testResults.filter((r) => r.success); if (successfulTests.length > 0) { const avgDuration = successfulTests.reduce((sum, t) => sum + t.duration, 0) / successfulTests.length; const maxDuration = Math.max(...successfulTests.map((t) => t.duration)); const minDuration = Math.min(...successfulTests.map((t) => t.duration)); log("⚑ μ„±λŠ₯ λ©”νŠΈλ¦­", "performance"); log(`평균 μ‘λ‹΅μ‹œκ°„: ${avgDuration.toFixed(2)}ms`, "performance"); log(`μ΅œλŒ€ μ‘λ‹΅μ‹œκ°„: ${maxDuration.toFixed(2)}ms`, "performance"); log(`μ΅œμ†Œ μ‘λ‹΅μ‹œκ°„: ${minDuration.toFixed(2)}ms`, "performance"); } // 상세 κ²°κ³Ό log("πŸ“‹ 상세 κ²°κ³Ό", "info"); testResults.forEach((result) => { const status = result.success ? "βœ…" : "❌"; const duration = result.duration.toFixed(2); log(` ${status} ${result.name}: ${duration}ms`, "info"); if (!result.success) { log(` 였λ₯˜: ${result.error}`, "error"); } }); return { total: tests.length, passed, failed, results: testResults, }; } // 슀크립트 μ‹€ν–‰ if (require.main === module) { runAllTests() .then((summary) => { log("🎯 λͺ¨λ“  ν…ŒμŠ€νŠΈ μ™„λ£Œ", "success"); process.exit(summary.failed === 0 ? 0 : 1); }) .catch((error) => { log(`μ˜ˆμƒμΉ˜ λͺ»ν•œ 였λ₯˜ λ°œμƒ: ${error.message}`, "error"); process.exit(1); }); } module.exports = { runAllTests, testResults, };