فهرست منبع

test: add brainstorm server integration tests

Jesse Vincent 7 ماه پیش
والد
کامیت
e76ffffc1d
3فایلهای تغییر یافته به همراه152 افزوده شده و 0 حذف شده
  1. 36 0
      tests/brainstorm-server/package-lock.json
  2. 10 0
      tests/brainstorm-server/package.json
  3. 106 0
      tests/brainstorm-server/server.test.js

+ 36 - 0
tests/brainstorm-server/package-lock.json

@@ -0,0 +1,36 @@
+{
+  "name": "brainstorm-server-tests",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "brainstorm-server-tests",
+      "version": "1.0.0",
+      "dependencies": {
+        "ws": "^8.19.0"
+      }
+    },
+    "node_modules/ws": {
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
+      "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10.0.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": ">=5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    }
+  }
+}

+ 10 - 0
tests/brainstorm-server/package.json

@@ -0,0 +1,10 @@
+{
+  "name": "brainstorm-server-tests",
+  "version": "1.0.0",
+  "scripts": {
+    "test": "node server.test.js"
+  },
+  "dependencies": {
+    "ws": "^8.19.0"
+  }
+}

+ 106 - 0
tests/brainstorm-server/server.test.js

@@ -0,0 +1,106 @@
+const { spawn } = require('child_process');
+const http = require('http');
+const WebSocket = require('ws');
+const fs = require('fs');
+const path = require('path');
+const assert = require('assert');
+
+const SERVER_PATH = path.join(__dirname, '../../lib/brainstorm-server/index.js');
+const TEST_PORT = 3334;
+const TEST_SCREEN = '/tmp/brainstorm-test/screen.html';
+
+// Clean up test directory
+function cleanup() {
+  if (fs.existsSync(path.dirname(TEST_SCREEN))) {
+    fs.rmSync(path.dirname(TEST_SCREEN), { recursive: true });
+  }
+}
+
+async function sleep(ms) {
+  return new Promise(resolve => setTimeout(resolve, ms));
+}
+
+async function fetch(url) {
+  return new Promise((resolve, reject) => {
+    http.get(url, (res) => {
+      let data = '';
+      res.on('data', chunk => data += chunk);
+      res.on('end', () => resolve({ status: res.statusCode, body: data }));
+    }).on('error', reject);
+  });
+}
+
+async function runTests() {
+  cleanup();
+
+  // Start server
+  const server = spawn('node', [SERVER_PATH], {
+    env: { ...process.env, BRAINSTORM_PORT: TEST_PORT, BRAINSTORM_SCREEN: TEST_SCREEN }
+  });
+
+  let stdout = '';
+  server.stdout.on('data', (data) => { stdout += data.toString(); });
+  server.stderr.on('data', (data) => { console.error('Server stderr:', data.toString()); });
+
+  await sleep(1000); // Wait for server to start
+
+  try {
+    // Test 1: Server starts and outputs JSON
+    console.log('Test 1: Server startup message');
+    assert(stdout.includes('server-started'), 'Should output server-started');
+    assert(stdout.includes(TEST_PORT.toString()), 'Should include port');
+    console.log('  PASS');
+
+    // Test 2: GET / returns HTML with helper injected
+    console.log('Test 2: Serves HTML with helper injected');
+    const res = await fetch(`http://localhost:${TEST_PORT}/`);
+    assert.strictEqual(res.status, 200);
+    assert(res.body.includes('brainstorm'), 'Should include brainstorm content');
+    assert(res.body.includes('WebSocket'), 'Should have helper.js injected');
+    console.log('  PASS');
+
+    // Test 3: WebSocket connection and event relay
+    console.log('Test 3: WebSocket relays events to stdout');
+    stdout = ''; // Reset stdout capture
+    const ws = new WebSocket(`ws://localhost:${TEST_PORT}`);
+    await new Promise(resolve => ws.on('open', resolve));
+
+    ws.send(JSON.stringify({ type: 'click', text: 'Test Button' }));
+    await sleep(300);
+
+    assert(stdout.includes('user-event'), 'Should relay user events');
+    assert(stdout.includes('Test Button'), 'Should include event data');
+    ws.close();
+    console.log('  PASS');
+
+    // Test 4: File change triggers reload notification
+    console.log('Test 4: File change notifies browsers');
+    const ws2 = new WebSocket(`ws://localhost:${TEST_PORT}`);
+    await new Promise(resolve => ws2.on('open', resolve));
+
+    let gotReload = false;
+    ws2.on('message', (data) => {
+      const msg = JSON.parse(data.toString());
+      if (msg.type === 'reload') gotReload = true;
+    });
+
+    // Modify the screen file
+    fs.writeFileSync(TEST_SCREEN, '<html><body>Updated</body></html>');
+    await sleep(500);
+
+    assert(gotReload, 'Should send reload message on file change');
+    ws2.close();
+    console.log('  PASS');
+
+    console.log('\nAll tests passed!');
+
+  } finally {
+    server.kill();
+    cleanup();
+  }
+}
+
+runTests().catch(err => {
+  console.error('Test failed:', err);
+  process.exit(1);
+});