server.test.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. const { spawn } = require('child_process');
  2. const http = require('http');
  3. const WebSocket = require('ws');
  4. const fs = require('fs');
  5. const path = require('path');
  6. const assert = require('assert');
  7. const SERVER_PATH = path.join(__dirname, '../../lib/brainstorm-server/index.js');
  8. const TEST_PORT = 3334;
  9. const TEST_SCREEN = '/tmp/brainstorm-test/screen.html';
  10. // Clean up test directory
  11. function cleanup() {
  12. if (fs.existsSync(path.dirname(TEST_SCREEN))) {
  13. fs.rmSync(path.dirname(TEST_SCREEN), { recursive: true });
  14. }
  15. }
  16. async function sleep(ms) {
  17. return new Promise(resolve => setTimeout(resolve, ms));
  18. }
  19. async function fetch(url) {
  20. return new Promise((resolve, reject) => {
  21. http.get(url, (res) => {
  22. let data = '';
  23. res.on('data', chunk => data += chunk);
  24. res.on('end', () => resolve({ status: res.statusCode, body: data }));
  25. }).on('error', reject);
  26. });
  27. }
  28. async function runTests() {
  29. cleanup();
  30. // Start server
  31. const server = spawn('node', [SERVER_PATH], {
  32. env: { ...process.env, BRAINSTORM_PORT: TEST_PORT, BRAINSTORM_SCREEN: TEST_SCREEN }
  33. });
  34. let stdout = '';
  35. server.stdout.on('data', (data) => { stdout += data.toString(); });
  36. server.stderr.on('data', (data) => { console.error('Server stderr:', data.toString()); });
  37. await sleep(1000); // Wait for server to start
  38. try {
  39. // Test 1: Server starts and outputs JSON
  40. console.log('Test 1: Server startup message');
  41. assert(stdout.includes('server-started'), 'Should output server-started');
  42. assert(stdout.includes(TEST_PORT.toString()), 'Should include port');
  43. console.log(' PASS');
  44. // Test 2: GET / returns HTML with helper injected
  45. console.log('Test 2: Serves HTML with helper injected');
  46. const res = await fetch(`http://localhost:${TEST_PORT}/`);
  47. assert.strictEqual(res.status, 200);
  48. assert(res.body.includes('brainstorm'), 'Should include brainstorm content');
  49. assert(res.body.includes('WebSocket'), 'Should have helper.js injected');
  50. console.log(' PASS');
  51. // Test 3: WebSocket connection and event relay
  52. console.log('Test 3: WebSocket relays events to stdout');
  53. stdout = ''; // Reset stdout capture
  54. const ws = new WebSocket(`ws://localhost:${TEST_PORT}`);
  55. await new Promise(resolve => ws.on('open', resolve));
  56. ws.send(JSON.stringify({ type: 'click', text: 'Test Button' }));
  57. await sleep(300);
  58. assert(stdout.includes('"source":"user-event"'), 'Should relay user events with source field');
  59. assert(stdout.includes('Test Button'), 'Should include event data');
  60. ws.close();
  61. console.log(' PASS');
  62. // Test 4: File change triggers reload notification
  63. console.log('Test 4: File change notifies browsers');
  64. const ws2 = new WebSocket(`ws://localhost:${TEST_PORT}`);
  65. await new Promise(resolve => ws2.on('open', resolve));
  66. let gotReload = false;
  67. ws2.on('message', (data) => {
  68. const msg = JSON.parse(data.toString());
  69. if (msg.type === 'reload') gotReload = true;
  70. });
  71. // Modify the screen file
  72. fs.writeFileSync(TEST_SCREEN, '<html><body>Updated</body></html>');
  73. await sleep(500);
  74. assert(gotReload, 'Should send reload message on file change');
  75. ws2.close();
  76. console.log(' PASS');
  77. console.log('\nAll tests passed!');
  78. } finally {
  79. server.kill();
  80. cleanup();
  81. }
  82. }
  83. runTests().catch(err => {
  84. console.error('Test failed:', err);
  85. process.exit(1);
  86. });