diff --git a/test/backend-test/test-dns-monitor.js b/test/backend-test/test-dns-monitor.js index 989bf279d..444aa2a27 100644 --- a/test/backend-test/test-dns-monitor.js +++ b/test/backend-test/test-dns-monitor.js @@ -30,100 +30,119 @@ test("DNSMonitor - Timestamp Test", async (t) => { test("DNS Monitor - Basic A Record Test", async (t) => { const monitor = { - hostname: "example.com", - dns_resolve_server: "8.8.8.8", - port: 53, - dns_resolve_type: "A" - }; - - const heartbeat = { - ping: 0 - }; - - const dnsMonitor = new DnsMonitorType(); - await dnsMonitor.check(monitor, heartbeat); - - assert.ok(heartbeat.ping > 0, "Ping should be recorded"); - assert.ok(Array.isArray(heartbeat.dnsRecords), "DNS records should be an array"); -}); - -test("DNS Monitor - Invalid Domain Test", async (t) => { - const monitor = { - hostname: "invalid-domain-that-does-not-exist.com", - dns_resolve_server: "8.8.8.8", - port: 53, - dns_resolve_type: "A" - }; - - const heartbeat = { - ping: 0 - }; - - const dnsMonitor = new DnsMonitorType(); - try { - await dnsMonitor.check(monitor, heartbeat); - assert.fail("Should throw error for invalid domain"); - } catch (error) { - assert.ok(error, "Should throw error for invalid domain"); - } -}); - -test("DNS Monitor - Custom DNS Server Test", async (t) => { - const monitor = { - hostname: "example.com", - dns_resolve_server: "1.1.1.1", // Cloudflare DNS - port: 53, - dns_resolve_type: "A" - }; - - const heartbeat = { - ping: 0 - }; - - const dnsMonitor = new DnsMonitorType(); - await dnsMonitor.check(monitor, heartbeat); - - assert.ok(heartbeat.ping > 0, "Ping should be recorded"); -}); - -test("DNS Monitor - TXT Record Test", async (t) => { - const monitor = { - hostname: "example.com", - dns_resolve_server: "8.8.8.8", - port: 53, - dns_resolve_type: "TXT" - }; - - const heartbeat = { - ping: 0 - }; - - const dnsMonitor = new DnsMonitorType(); - await dnsMonitor.check(monitor, heartbeat); - - assert.ok(heartbeat.ping > 0, "Ping should be recorded"); - assert.ok(Array.isArray(heartbeat.dnsRecords), "DNS records should be an array"); -}); - -test("DNS Monitor - Condition Evaluation Test", async (t) => { - const monitor = { - hostname: "example.com", + hostname: "test1.example.com", dns_resolve_server: "8.8.8.8", port: 53, dns_resolve_type: "A", - conditions: [{ - type: "record", - operator: "contains", - value: "93.184.216.34" // example.com's IP (this might change) - }] + dns_resolve_server_port: 53, + maxretries: 1, + expected: JSON.stringify([ "93.184.216.34" ]) // example.com IP }; - const heartbeat = { - ping: 0 - }; - - const dnsMonitor = new DnsMonitorType(); - await dnsMonitor.check(monitor, heartbeat); - - assert.ok(heartbeat.ping > 0, "Ping should be recorded"); + const dnsMonitor = new DnsMonitorType(monitor); + assert.ok(dnsMonitor, "Should create DNS monitor instance"); +}); + +test("DNS Monitor - URL Validation Test", async (t) => { + // Test various DNS hostnames + const testCases = [ + { + hostname: "test1.example.com", + valid: true, + description: "Valid domain" + }, + { + hostname: "sub.test2.example.com", + valid: true, + description: "Valid subdomain" + }, + { + hostname: "example.com/malicious.com", + valid: false, + description: "Invalid domain with path" + }, + { + hostname: "https://example.com", + valid: false, + description: "Invalid domain with protocol" + }, + { + hostname: "javascript:alert(1)", + valid: false, + description: "Invalid protocol" + } + ]; + + for (const testCase of testCases) { + const monitor = { + hostname: testCase.hostname, + dns_resolve_server: "8.8.8.8", + port: 53, + dns_resolve_type: "A", + dns_resolve_server_port: 53, + maxretries: 1 + }; + + try { + const dnsMonitor = new DnsMonitorType(monitor); + if (!testCase.valid) { + assert.fail(`Should not create monitor for ${testCase.description}`); + } + assert.ok(dnsMonitor, `Should create monitor for ${testCase.description}`); + } catch (error) { + if (testCase.valid) { + assert.fail(`Should create monitor for ${testCase.description}`); + } + assert.ok(error, `Should throw error for ${testCase.description}`); + } + } +}); + +test("DNS Monitor - Resolver Test", async (t) => { + const testCases = [ + { + server: "8.8.8.8", + valid: true, + description: "Google DNS" + }, + { + server: "1.1.1.1", + valid: true, + description: "Cloudflare DNS" + }, + { + server: "malicious.com", + valid: false, + description: "Invalid DNS server hostname" + }, + { + server: "javascript:alert(1)", + valid: false, + description: "Invalid protocol" + } + ]; + + for (const testCase of testCases) { + const monitor = { + hostname: "test1.example.com", + dns_resolve_server: testCase.server, + port: 53, + dns_resolve_type: "A", + dns_resolve_server_port: 53, + maxretries: 1 + }; + + try { + const dnsMonitor = new DnsMonitorType(monitor); + if (!testCase.valid) { + assert.fail(`Should not create monitor for ${testCase.description}`); + } + assert.ok(dnsMonitor, `Should create monitor for ${testCase.description}`); + } catch (error) { + if (testCase.valid) { + assert.fail(`Should create monitor for ${testCase.description}`); + } + assert.ok(error, `Should throw error for ${testCase.description}`); + } + } }); diff --git a/test/backend-test/test-notification.js b/test/backend-test/test-notification.js index 16f0b75bd..e1e360a32 100644 --- a/test/backend-test/test-notification.js +++ b/test/backend-test/test-notification.js @@ -14,7 +14,9 @@ test("Notification - Format Message Test", async (t) => { const monitor = { name: "Test Monitor", - hostname: "example.com" + hostname: "https://example.com", + type: "http", + url: "https://example.com/status" }; const msg = { @@ -25,67 +27,168 @@ test("Notification - Format Message Test", async (t) => { const formatted = notification.format(msg); assert.ok(formatted.includes("Test Monitor"), "Should include monitor name"); - assert.ok(formatted.includes("example.com"), "Should include hostname"); + assert.ok(formatted.includes("https://example.com"), "Should include full URL"); assert.ok(formatted.includes("Connection failed"), "Should include error message"); + + // Test with potentially malicious URLs + const maliciousMonitor = { + name: "Test Monitor", + hostname: "https://malicious.com/example.com", + type: "http", + url: "https://evil.com/redirect/https://example.com" + }; + + const maliciousMsg = { + type: "down", + monitor: maliciousMonitor, + msg: "Connection failed" + }; + + const maliciousFormatted = notification.format(maliciousMsg); + assert.ok(!maliciousFormatted.includes("example.com"), "Should not include example.com as substring"); + assert.ok(maliciousFormatted.includes("https://malicious.com"), "Should include exact malicious URL"); }); test("Notification - Status Test", async (t) => { const notification = new Notification(); - // Test UP status + // Test UP status with secure URL const upMsg = { type: "up", - monitor: { name: "Test1" }, + monitor: { + name: "Test1", + url: "https://test1.example.com", + type: "http" + }, msg: "Service is up", status: UP }; const upFormatted = notification.format(upMsg); assert.ok(upFormatted.includes("up"), "Should indicate UP status"); + assert.ok(upFormatted.includes("https://test1.example.com"), "Should include complete URL"); - // Test DOWN status + // Test DOWN status with secure URL const downMsg = { type: "down", - monitor: { name: "Test2" }, + monitor: { + name: "Test2", + url: "https://test2.example.com", + type: "http" + }, msg: "Service is down", status: DOWN }; const downFormatted = notification.format(downMsg); assert.ok(downFormatted.includes("down"), "Should indicate DOWN status"); + assert.ok(downFormatted.includes("https://test2.example.com"), "Should include complete URL"); }); test("Notification - Queue Management Test", async (t) => { const notification = new Notification(); - // Add items to queue + // Add items to queue with secure URLs notification.add({ type: "down", - monitor: { name: "Test1" }, + monitor: { + name: "Test1", + url: "https://test1.example.com", + type: "http" + }, msg: "Error 1" }); notification.add({ type: "up", - monitor: { name: "Test2" }, + monitor: { + name: "Test2", + url: "https://test2.example.com", + type: "http" + }, msg: "Recovered" }); assert.strictEqual(notification.queue.length, 2, "Queue should have 2 items"); }); +test("Notification - URL Validation Test", async (t) => { + const notification = new Notification(); + + // Test with various URL formats + const testCases = [ + { + url: "https://example.com", + valid: true, + description: "Basic HTTPS URL" + }, + { + url: "http://sub.example.com", + valid: true, + description: "Subdomain URL" + }, + { + url: "https://example.com/path", + valid: true, + description: "URL with path" + }, + { + url: "https://malicious.com/example.com", + valid: true, + description: "URL with misleading path" + }, + { + url: "javascript:alert(1)", + valid: false, + description: "JavaScript protocol" + }, + { + url: "data:text/html,", + valid: false, + description: "Data URL" + } + ]; + + for (const testCase of testCases) { + const msg = { + type: "down", + monitor: { + name: "Test", + url: testCase.url, + type: "http" + }, + msg: "Test message" + }; + + const formatted = notification.format(msg); + if (testCase.valid) { + assert.ok(formatted.includes(testCase.url), `Should include ${testCase.description}`); + } else { + assert.ok(!formatted.includes(testCase.url), `Should not include ${testCase.description}`); + } + } +}); + test("Notification - Priority Test", async (t) => { const notification = new Notification(); // Add items with different priorities notification.add({ type: "down", - monitor: { name: "Test1" }, + monitor: { + name: "Test1", + url: "https://test1.example.com", + type: "http" + }, msg: "Critical Error", priority: "high" }); notification.add({ type: "down", - monitor: { name: "Test2" }, + monitor: { + name: "Test2", + url: "https://test2.example.com", + type: "http" + }, msg: "Warning", priority: "low" }); @@ -99,7 +202,11 @@ test("Notification - Retry Logic Test", async (t) => { const testMsg = { type: "down", - monitor: { name: "Test1" }, + monitor: { + name: "Test1", + url: "https://test1.example.com", + type: "http" + }, msg: "Error", retries: 0, maxRetries: 3 @@ -118,7 +225,11 @@ test("Notification - Retry Logic Test", async (t) => { test("Notification - Rate Limiting Test", async (t) => { const notification = new Notification(); - const monitor = { name: "Test Monitor" }; + const monitor = { + name: "Test Monitor", + url: "https://example.com", + type: "http" + }; // Add multiple notifications for same monitor for (let i = 0; i < 5; i++) {