diff --git a/tests/real-plugin.spec.ts b/tests/real-plugin.spec.ts index e21ddf8..bf669d0 100644 --- a/tests/real-plugin.spec.ts +++ b/tests/real-plugin.spec.ts @@ -1,55 +1,36 @@ -/** - * Real Plugin Integration Test - * - * This test verifies the real OpenClaw plugin (installed on vps.t1) - * can successfully connect to and report telemetry to HarborForge Backend. - * - * Prerequisites: - * - vps.t1 must have HarborForge.OpenclawPlugin installed - * - vps.t1's OpenClaw Gateway must be running with plugin enabled - * - Backend must be accessible from vps.t1 - * - * Run with: ./run-test-frontend.sh --expose-port on --test-real-plugin - */ +import { test, expect } from "@playwright/test"; -import { test, expect } from '@playwright/test'; +const BACKEND_URL = process.env.BACKEND_URL || "http://backend:8000"; +const PLUGIN_SERVER_URL = process.env.PLUGIN_SERVER_URL || "https://vps.t1:8000"; +const TEST_TIMEOUT = 120000; -// Configuration from environment -const BACKEND_URL = process.env.BACKEND_URL || 'http://backend:8000'; -const PLUGIN_SERVER_URL = process.env.PLUGIN_SERVER_URL || 'https://vps.t1:8000'; -const TEST_TIMEOUT = 120000; // 2 minutes for real plugin communication - -test.describe('Real OpenClaw Plugin Integration', () => { +test.describe("Real OpenClaw Plugin Integration", () => { test.setTimeout(TEST_TIMEOUT); test.beforeAll(async () => { - console.log('🔌 Testing real plugin integration...'); - console.log(` Backend: ${BACKEND_URL}`); - console.log(` Plugin Server: ${PLUGIN_SERVER_URL}`); + console.log("🔌 Testing real plugin integration..."); + console.log(" Backend: " + BACKEND_URL); + console.log(" Plugin Server: " + PLUGIN_SERVER_URL); }); - /** - * Test 1: Verify plugin can register server and get API key - */ - test('should register server and generate API key', async ({ request }) => { - // Login as admin to get session - const loginRes = await request.post(`${BACKEND_URL}/auth/login`, { - data: { - username: 'admin', - password: 'admin123', // Default test password - }, + async function loginAsAdmin(request: any) { + const loginRes = await request.post(BACKEND_URL + "/auth/token", { + form: { username: "admin", password: "admin123" }, + headers: { "Content-Type": "application/x-www-form-urlencoded" }, }); - expect(loginRes.ok()).toBeTruthy(); const loginData = await loginRes.json(); - const token = loginData.access_token; + return loginData.access_token; + } + + test("should register server and generate API key", async ({ request }) => { + const token = await loginAsAdmin(request); - // Register a new server for testing - const serverRes = await request.post(`${BACKEND_URL}/monitor/admin/servers`, { - headers: { 'Authorization': `Bearer ${token}` }, + const serverRes = await request.post(BACKEND_URL + "/monitor/admin/servers", { + headers: { Authorization: "Bearer " + token }, data: { - identifier: 'test-real-plugin-vps-t1', - display_name: 'Test Real Plugin on vps.t1', + identifier: "test-real-plugin-vps-t1", + display_name: "Test Real Plugin on vps.t1", }, }); @@ -57,11 +38,10 @@ test.describe('Real OpenClaw Plugin Integration', () => { const serverData = await serverRes.json(); const serverId = serverData.id; - console.log(`✅ Server registered: ID=${serverId}`); + console.log("✅ Server registered: ID=" + serverId); - // Generate API key for this server - const apiKeyRes = await request.post(`${BACKEND_URL}/monitor/admin/servers/${serverId}/api-key`, { - headers: { 'Authorization': `Bearer ${token}` }, + const apiKeyRes = await request.post(BACKEND_URL + "/monitor/admin/servers/" + serverId + "/api-key", { + headers: { Authorization: "Bearer " + token }, }); expect(apiKeyRes.ok()).toBeTruthy(); @@ -70,32 +50,25 @@ test.describe('Real OpenClaw Plugin Integration', () => { expect(apiKeyData.api_key).toBeDefined(); expect(apiKeyData.api_key.length).toBeGreaterThan(30); - console.log(`✅ API Key generated: ${apiKeyData.api_key.substring(0, 10)}...`); + console.log("✅ API Key generated: " + apiKeyData.api_key.substring(0, 10) + "..."); - // Store for subsequent tests process.env.TEST_SERVER_ID = String(serverId); process.env.TEST_API_KEY = apiKeyData.api_key; }); - /** - * Test 2: Verify plugin can send heartbeat with valid API key - */ - test('should receive heartbeat from real plugin', async ({ request }) => { + test("should receive heartbeat from real plugin", async ({ request }) => { const apiKey = process.env.TEST_API_KEY; const serverId = process.env.TEST_SERVER_ID; expect(apiKey).toBeDefined(); expect(serverId).toBeDefined(); - // Simulate a heartbeat from the plugin (as if vps.t1 sent it) - const heartbeatRes = await request.post(`${BACKEND_URL}/monitor/server/heartbeat-v2`, { - headers: { 'X-API-Key': apiKey }, + const heartbeatRes = await request.post(BACKEND_URL + "/monitor/server/heartbeat-v2", { + headers: { "X-API-Key": apiKey }, data: { - identifier: 'test-real-plugin-vps-t1', - openclaw_version: '0.1.0-test', - agents: [ - { id: 'agent-1', name: 'TestAgent', status: 'active' } - ], + identifier: "test-real-plugin-vps-t1", + openclaw_version: "0.1.0-test", + agents: [{ id: "agent-1", name: "TestAgent", status: "active" }], cpu_pct: 45.5, mem_pct: 60.2, disk_pct: 70.1, @@ -110,36 +83,22 @@ test.describe('Real OpenClaw Plugin Integration', () => { expect(heartbeatData.ok).toBe(true); expect(heartbeatData.server_id).toBe(parseInt(serverId)); - expect(heartbeatData.identifier).toBe('test-real-plugin-vps-t1'); + expect(heartbeatData.identifier).toBe("test-real-plugin-vps-t1"); expect(heartbeatData.last_seen_at).toBeDefined(); - console.log('✅ Heartbeat accepted by backend'); - console.log(` Server ID: ${heartbeatData.server_id}`); - console.log(` Last seen: ${heartbeatData.last_seen_at}`); + console.log("✅ Heartbeat accepted by backend"); }); - /** - * Test 3: Verify heartbeat data is stored in database - */ - test('should persist telemetry data to database', async ({ request }) => { + test("should persist telemetry data to database", async ({ request }) => { const apiKey = process.env.TEST_API_KEY; const serverId = process.env.TEST_SERVER_ID; - // Wait a moment for data to be persisted await new Promise(resolve => setTimeout(resolve, 1000)); - // Login as admin - const loginRes = await request.post(`${BACKEND_URL}/auth/login`, { - data: { username: 'admin', password: 'admin123' }, - }); + const token = await loginAsAdmin(request); - expect(loginRes.ok()).toBeTruthy(); - const loginData = await loginRes.json(); - const token = loginData.access_token; - - // Query server state - const stateRes = await request.get(`${BACKEND_URL}/monitor/admin/servers`, { - headers: { 'Authorization': `Bearer ${token}` }, + const stateRes = await request.get(BACKEND_URL + "/monitor/admin/servers", { + headers: { Authorization: "Bearer " + token }, }); expect(stateRes.ok()).toBeTruthy(); @@ -148,120 +107,79 @@ test.describe('Real OpenClaw Plugin Integration', () => { const testServer = servers.find((s: any) => s.id === parseInt(serverId)); expect(testServer).toBeDefined(); - // Verify telemetry fields are stored - expect(testServer.openclaw_version).toBe('0.1.0-test'); + expect(testServer.openclaw_version).toBe("0.1.0-test"); expect(testServer.cpu_pct).toBeCloseTo(45.5, 1); expect(testServer.mem_pct).toBeCloseTo(60.2, 1); expect(testServer.last_seen_at).toBeDefined(); - console.log('✅ Telemetry data persisted:'); - console.log(` Version: ${testServer.openclaw_version}`); - console.log(` CPU: ${testServer.cpu_pct}%`); - console.log(` Memory: ${testServer.mem_pct}%`); + console.log("✅ Telemetry data persisted"); }); - /** - * Test 4: Verify invalid API key is rejected - */ - test('should reject heartbeat with invalid API key', async ({ request }) => { - const heartbeatRes = await request.post(`${BACKEND_URL}/monitor/server/heartbeat-v2`, { - headers: { 'X-API-Key': 'invalid-api-key-12345' }, + test("should reject heartbeat with invalid API key", async ({ request }) => { + const heartbeatRes = await request.post(BACKEND_URL + "/monitor/server/heartbeat-v2", { + headers: { "X-API-Key": "invalid-api-key-12345" }, data: { - identifier: 'test-real-plugin-vps-t1', - openclaw_version: '0.1.0-test', + identifier: "test-real-plugin-vps-t1", + openclaw_version: "0.1.0-test", }, }); expect(heartbeatRes.status()).toBe(401); const errorData = await heartbeatRes.json(); + expect(errorData.detail).toContain("Invalid"); - expect(errorData.detail).toContain('Invalid'); - - console.log('✅ Invalid API key correctly rejected (401)'); + console.log("✅ Invalid API key correctly rejected (401)"); }); - /** - * Test 5: Verify missing API key is rejected - */ - test('should reject heartbeat without API key', async ({ request }) => { - const heartbeatRes = await request.post(`${BACKEND_URL}/monitor/server/heartbeat-v2`, { + test("should reject heartbeat without API key", async ({ request }) => { + const heartbeatRes = await request.post(BACKEND_URL + "/monitor/server/heartbeat-v2", { data: { - identifier: 'test-real-plugin-vps-t1', - openclaw_version: '0.1.0-test', + identifier: "test-real-plugin-vps-t1", + openclaw_version: "0.1.0-test", }, }); - expect(heartbeatRes.status()).toBe(422); // FastAPI validation error - - console.log('✅ Missing API key correctly rejected (422)'); + expect(heartbeatRes.status()).toBe(422); + console.log("✅ Missing API key correctly rejected (422)"); }); - /** - * Test 6: Test API key revocation - */ - test('should revoke API key and reject subsequent heartbeats', async ({ request }) => { + test("should revoke API key and reject subsequent heartbeats", async ({ request }) => { const apiKey = process.env.TEST_API_KEY; const serverId = process.env.TEST_SERVER_ID; - // Login as admin - const loginRes = await request.post(`${BACKEND_URL}/auth/login`, { - data: { username: 'admin', password: 'admin123' }, - }); + const token = await loginAsAdmin(request); - expect(loginRes.ok()).toBeTruthy(); - const loginData = await loginRes.json(); - const token = loginData.access_token; - - // Revoke API key - const revokeRes = await request.delete(`${BACKEND_URL}/monitor/admin/servers/${serverId}/api-key`, { - headers: { 'Authorization': `Bearer ${token}` }, + const revokeRes = await request.delete(BACKEND_URL + "/monitor/admin/servers/" + serverId + "/api-key", { + headers: { Authorization: "Bearer " + token }, }); expect(revokeRes.status()).toBe(204); + console.log("✅ API key revoked"); - console.log('✅ API key revoked'); - - // Try to use revoked key - const heartbeatRes = await request.post(`${BACKEND_URL}/monitor/server/heartbeat-v2`, { - headers: { 'X-API-Key': apiKey }, + const heartbeatRes = await request.post(BACKEND_URL + "/monitor/server/heartbeat-v2", { + headers: { "X-API-Key": apiKey }, data: { - identifier: 'test-real-plugin-vps-t1', - openclaw_version: '0.1.0-test', + identifier: "test-real-plugin-vps-t1", + openclaw_version: "0.1.0-test", }, }); expect(heartbeatRes.status()).toBe(401); - - console.log('✅ Revoked API key correctly rejected'); + console.log("✅ Revoked API key correctly rejected"); }); - /** - * Cleanup: Delete test server - */ test.afterAll(async ({ request }) => { const serverId = process.env.TEST_SERVER_ID; if (!serverId) return; try { - const loginRes = await request.post(`${BACKEND_URL}/auth/login`, { - data: { username: 'admin', password: 'admin123' }, + const token = await loginAsAdmin(request); + await request.delete(BACKEND_URL + "/monitor/admin/servers/" + serverId, { + headers: { Authorization: "Bearer " + token }, }); - - if (!loginRes.ok()) return; - - const loginData = await loginRes.json(); - const token = loginData.access_token; - - // Delete test server - const deleteRes = await request.delete(`${BACKEND_URL}/monitor/admin/servers/${serverId}`, { - headers: { 'Authorization': `Bearer ${token}` }, - }); - - if (deleteRes.status() === 204) { - console.log(`✅ Test server ${serverId} cleaned up`); - } + console.log("✅ Test server " + serverId + " cleaned up"); } catch (e) { - console.log(`⚠️ Cleanup warning: ${e}`); + console.log("⚠️ Cleanup warning: " + e); } }); });