bun-ui-tests 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/cli.ts +78 -70
  2. package/package.json +1 -1
  3. package/ui-runner.ts +41 -86
package/cli.ts CHANGED
@@ -12,7 +12,13 @@ function getPackageRoot() {
12
12
  return import.meta.dir;
13
13
  }
14
14
 
15
- // 2. Tentar process.argv[1] (caminho do script)
15
+ // 2. Tentar via import.meta.url
16
+ try {
17
+ const __filename = fileURLToPath(import.meta.url);
18
+ return dirname(__filename);
19
+ } catch (e) {}
20
+
21
+ // 3. Tentar process.argv[1] (caminho do script)
16
22
  try {
17
23
  const argvPath = process.argv[1];
18
24
  if (argvPath) {
@@ -21,10 +27,10 @@ function getPackageRoot() {
21
27
  return dirname(argvPath);
22
28
  }
23
29
 
24
- // Se é um executável, procura node_modules
30
+ // Se é um executável, procura node_modules ou cache
25
31
  // bunx instala em: ~/.bun/install/cache/bun-ui-tests@version/
26
32
  const parts = argvPath.split('/');
27
- const cacheIndex = parts.findIndex(p => p === 'cache');
33
+ const cacheIndex = parts.findIndex(p => p === 'cache' || p === '.bun' || p === 'node_modules');
28
34
  if (cacheIndex !== -1 && cacheIndex + 1 < parts.length) {
29
35
  // Pega até o nome do pacote (ex: bun-ui-tests@1.0.5)
30
36
  const packagePath = parts.slice(0, cacheIndex + 2).join('/');
@@ -35,22 +41,62 @@ function getPackageRoot() {
35
41
  console.error('Error resolving from argv[1]:', e);
36
42
  }
37
43
 
38
- // 3. Fallback: usar diretório atual
39
- console.warn('⚠️ Could not determine package root, using current directory');
44
+ // 4. Fallback: usar diretório atual
40
45
  return process.cwd();
41
46
  }
42
47
 
43
48
  const packageRoot = getPackageRoot();
44
49
 
50
+ // Cores ANSI suaves
51
+ const colors = {
52
+ reset: "\x1b[0m",
53
+ red: "\x1b[31m",
54
+ green: "\x1b[32m",
55
+ yellow: "\x1b[33m",
56
+ blue: "\x1b[34m",
57
+ cyan: "\x1b[36m",
58
+ gray: "\x1b[90m"
59
+ };
60
+
45
61
  const COMMANDS = {
46
62
  run: "Run the test UI (production mode)",
47
63
  dev: "Run in development mode (hot reload)",
48
64
  help: "Show this help message"
49
65
  };
50
66
 
67
+ async function findVerifiedRoot(): Promise<string> {
68
+ const possibleRoots = [
69
+ getPackageRoot(),
70
+ process.cwd(),
71
+ dirname(fileURLToPath(import.meta.url)),
72
+ ];
73
+
74
+ for (const root of possibleRoots) {
75
+ if (!root) continue;
76
+ const runnerPath = join(root, "ui-runner.ts");
77
+ const distPath = join(root, "app", "dist", "index.html");
78
+
79
+ if (await Bun.file(runnerPath).exists() && await Bun.file(distPath).exists()) {
80
+ return root;
81
+ }
82
+ }
83
+
84
+ // Se não achou, tenta procurar subindo diretórios
85
+ try {
86
+ let current = getPackageRoot();
87
+ for (let i = 0; i < 3; i++) {
88
+ const runnerPath = join(current, "ui-runner.ts");
89
+ if (await Bun.file(runnerPath).exists()) return current;
90
+ current = dirname(current);
91
+ }
92
+ } catch (e) {}
93
+
94
+ return getPackageRoot();
95
+ }
96
+
51
97
  async function showHelp() {
52
98
  console.log(`
53
- 🧪 Bun Test UI - A beautiful UI for running Bun tests
99
+ ${colors.cyan}Bun Test UI${colors.reset} - A beautiful UI for running Bun tests
54
100
 
55
101
  Usage:
56
102
  bunx bun-ui-tests <command>
@@ -66,71 +112,35 @@ Examples:
66
112
  `);
67
113
  }
68
114
 
69
- async function checkBuildExists(): Promise<boolean> {
70
- const distPath = join(packageRoot, "app", "dist", "index.html");
71
-
72
- console.log(`🔍 Debug Info:`);
73
- console.log(` - process.argv[1]: ${process.argv[1]}`);
74
- console.log(` - Resolved packageRoot: ${packageRoot}`);
75
- console.log(` - Looking for: ${distPath}`);
115
+ async function checkBuildExists(root: string): Promise<boolean> {
116
+ const distPath = join(root, "app", "dist", "index.html");
76
117
 
77
118
  try {
78
- const exists = await Bun.file(distPath).exists();
79
- if (!exists) {
80
- console.log(` - File exists: NO ❌`);
81
-
82
- // Tentar procurar em locais alternativos
83
- const alternatives = [
84
- join(process.cwd(), "app", "dist", "index.html"),
85
- join(dirname(process.argv[0]), "app", "dist", "index.html"),
86
- ];
87
-
88
- console.log(`\n🔍 Trying alternative paths:`);
89
- for (const alt of alternatives) {
90
- const altExists = await Bun.file(alt).exists();
91
- console.log(` - ${alt}: ${altExists ? '✓' : '✗'}`);
92
- if (altExists) {
93
- return true;
94
- }
95
- }
96
- } else {
97
- console.log(` - File exists: YES ✓`);
98
- }
99
- return exists;
119
+ return await Bun.file(distPath).exists();
100
120
  } catch (err) {
101
- console.error(`❌ Error checking path:`, err);
102
121
  return false;
103
122
  }
104
123
  }
105
124
 
106
125
  async function runTestUI() {
107
- // Verifica se o build do frontend existe
108
- const buildExists = await checkBuildExists();
126
+ const root = await findVerifiedRoot();
127
+ const buildExists = await checkBuildExists(root);
109
128
 
110
129
  if (!buildExists) {
111
- console.log("\n⚠️ Frontend assets not found.\n");
130
+ console.log(`\n${colors.yellow}!${colors.reset} Frontend assets not found.\n`);
112
131
  console.log("This usually means one of:");
113
- console.log(" 1. The package wasn't built before publishing (contact maintainer)");
132
+ console.log(" 1. The package wasn't built before publishing");
114
133
  console.log(" 2. You're running from source (run: bun run build first)");
115
- console.log(" 3. Installation issue (try: npm cache clean --force)\n");
116
-
117
- console.log("💡 Temporary workaround:");
118
- console.log(" git clone https://github.com/KillDarkness/Bun-UI-Test.git");
119
- console.log(" cd Bun-UI-Test");
120
- console.log(" bun install");
121
- console.log(" cd app && bun install && bun run build && cd ..");
122
- console.log(" bun run ui-runner.ts\n");
134
+ console.log(" 3. Installation issue\n");
123
135
 
124
136
  process.exit(1);
125
137
  }
126
138
 
127
- console.log("🚀 Starting Bun Test UI (Production Mode)...\n");
128
- console.log("📡 WebSocket server: ws://localhost:5050/ws");
129
- console.log("🌐 Frontend: http://localhost:5050\n");
130
- console.log("Press Ctrl+C to stop\n");
139
+ console.log(`${colors.green}›${colors.reset} Starting Bun Test UI...`);
140
+ console.log(`${colors.gray}→ WebSocket: ws://localhost:5050/ws`);
141
+ console.log(`→ Frontend: http://localhost:5050${colors.reset}\n`);
131
142
 
132
- // Roda o script do backend diretamente com Bun
133
- const runnerScript = join(packageRoot, "ui-runner.ts");
143
+ const runnerScript = join(root, "ui-runner.ts");
134
144
 
135
145
  const proc = spawn("bun", ["run", runnerScript], {
136
146
  cwd: process.cwd(),
@@ -141,31 +151,31 @@ async function runTestUI() {
141
151
 
142
152
  proc.on("close", (code) => {
143
153
  if (code !== 0) {
144
- console.error(`\n Process exited with code ${code}`);
154
+ console.error(`\n${colors.red}✗${colors.reset} Process exited with code ${code}`);
145
155
  process.exit(code || 1);
146
156
  }
147
157
  });
148
158
 
149
159
  proc.on("error", (err) => {
150
- console.error("❌ Error starting test UI:", err);
160
+ console.error(`${colors.red}✗${colors.reset} Error starting test UI:`, err);
151
161
  process.exit(1);
152
162
  });
153
163
 
154
- // Handle Ctrl+C
155
164
  process.on("SIGINT", () => {
156
- console.log("\n\n👋 Stopping Bun Test UI...");
165
+ console.log(`\n\n${colors.gray}Stopping Bun Test UI...${colors.reset}`);
157
166
  proc.kill("SIGINT");
158
167
  process.exit(0);
159
168
  });
160
169
  }
161
170
 
162
171
  async function runDevMode() {
163
- console.log("🚀 Starting Bun Test UI (Development Mode)...\n");
164
- console.log("📡 WebSocket server: ws://localhost:5060");
165
- console.log("🌐 Frontend: http://localhost:5050 (with hot reload)\n");
166
- console.log("Press Ctrl+C to stop\n");
172
+ const root = await findVerifiedRoot();
173
+
174
+ console.log(`${colors.cyan}›${colors.reset} Starting Bun Test UI (Dev Mode)...`);
175
+ console.log(`${colors.gray}→ WebSocket: ws://localhost:5060`);
176
+ console.log(`→ Frontend: http://localhost:5050${colors.reset}\n`);
167
177
 
168
- const backendPath = join(packageRoot, "ui-runner.ts");
178
+ const backendPath = join(root, "ui-runner.ts");
169
179
  const backendProc = spawn("bun", ["run", backendPath], {
170
180
  cwd: process.cwd(),
171
181
  stdio: "inherit",
@@ -175,7 +185,7 @@ async function runDevMode() {
175
185
 
176
186
  await new Promise(resolve => setTimeout(resolve, 1000));
177
187
 
178
- const appDir = join(packageRoot, "app");
188
+ const appDir = join(root, "app");
179
189
  const frontendProc = spawn("bun", ["run", "dev"], {
180
190
  cwd: appDir,
181
191
  stdio: "inherit",
@@ -183,20 +193,18 @@ async function runDevMode() {
183
193
  });
184
194
 
185
195
  process.on("SIGINT", () => {
186
- console.log("\n\n👋 Stopping Bun Test UI...");
196
+ console.log(`\n\n${colors.gray}Stopping Bun Test UI...${colors.reset}`);
187
197
  backendProc.kill("SIGINT");
188
198
  frontendProc.kill("SIGINT");
189
199
  process.exit(0);
190
200
  });
191
201
 
192
202
  backendProc.on("close", (code) => {
193
- console.log("\n❌ Backend stopped");
194
203
  frontendProc.kill("SIGINT");
195
204
  process.exit(code || 1);
196
205
  });
197
206
 
198
207
  frontendProc.on("close", (code) => {
199
- console.log("\n❌ Frontend stopped");
200
208
  backendProc.kill("SIGINT");
201
209
  process.exit(code || 1);
202
210
  });
@@ -209,7 +217,7 @@ switch (command) {
209
217
  case "run":
210
218
  runTestUI()
211
219
  .catch((err) => {
212
- console.error("❌ Failed to start:", err);
220
+ console.error(`${colors.red}✗${colors.reset} Failed to start:`, err);
213
221
  process.exit(1);
214
222
  });
215
223
  break;
@@ -217,7 +225,7 @@ switch (command) {
217
225
  case "dev":
218
226
  runDevMode()
219
227
  .catch((err) => {
220
- console.error("❌ Failed to start dev mode:", err);
228
+ console.error(`${colors.red}✗${colors.reset} Failed to start dev mode:`, err);
221
229
  process.exit(1);
222
230
  });
223
231
  break;
@@ -229,7 +237,7 @@ switch (command) {
229
237
  break;
230
238
 
231
239
  default:
232
- console.error(`❌ Unknown command: ${command}\n`);
240
+ console.error(`${colors.red}✗${colors.reset} Unknown command: ${command}\n`);
233
241
  showHelp();
234
242
  process.exit(1);
235
243
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bun-ui-tests",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "A beautiful UI for running Bun tests",
5
5
  "type": "module",
6
6
  "bin": {
package/ui-runner.ts CHANGED
@@ -14,42 +14,60 @@
14
14
  import { spawn } from "node:child_process";
15
15
  import { readdir, readFile, stat } from "node:fs/promises";
16
16
  import { join, relative, dirname } from "node:path";
17
+ import { fileURLToPath } from "node:url";
17
18
 
18
19
  // Determina o diretório do executável ou script
19
20
  const getBaseDir = () => {
20
- // Se rodando como executável compilado, pega o diretório onde o CLI foi instalado
21
- if (import.meta.path && !import.meta.path.endsWith('.ts')) {
22
- return dirname(process.execPath);
21
+ // 1. Tentar import.meta.dir (Bun específico)
22
+ if (import.meta.dir) {
23
+ return import.meta.dir;
23
24
  }
25
+
26
+ // 2. Tentar via import.meta.url
27
+ try {
28
+ const __filename = fileURLToPath(import.meta.url);
29
+ return dirname(__filename);
30
+ } catch (e) {}
24
31
 
25
- // Try process.argv[1] to find real path
32
+ // 3. Try process.argv[1] to find real path
26
33
  try {
27
34
  const argvPath = process.argv[1];
28
- if (argvPath && argvPath.endsWith("ui-runner.ts")) {
35
+ if (argvPath) {
36
+ // Se rodando como executável compilado, pega o diretório onde o CLI foi instalado
37
+ if (import.meta.path && !import.meta.path.endsWith('.ts')) {
38
+ return dirname(process.execPath);
39
+ }
29
40
  return dirname(argvPath);
30
41
  }
31
42
  } catch (e) {}
32
43
 
33
- // Se rodando como script .ts, usa o dir do próprio arquivo
34
- return import.meta.dir;
44
+ // Se tudo falhar
45
+ return process.cwd();
46
+ };
47
+
48
+ const colors = {
49
+ reset: "\x1b[0m",
50
+ red: "\x1b[31m",
51
+ green: "\x1b[32m",
52
+ yellow: "\x1b[33m",
53
+ blue: "\x1b[34m",
54
+ cyan: "\x1b[36m",
55
+ gray: "\x1b[90m"
35
56
  };
36
57
 
37
58
  const baseDir = getBaseDir();
38
59
  const distPath = join(baseDir, "app", "dist");
39
- console.log(`Debug: ui-runner argv[1] is ${process.argv[1]}`);
40
- console.log(`Debug: distPath is ${distPath}`);
41
60
  const isDevMode = process.env.BUN_TEST_UI_DEV === "true";
42
61
 
43
62
  // WebSocket Handler (lógica compartilhada)
44
63
  const websocketHandler = {
45
64
  async open(ws: any) {
46
- console.log("✓ UI connected");
65
+ console.log(`${colors.green}✓${colors.reset} UI connected`);
47
66
 
48
67
  // Escaneia arquivos de teste
49
68
  const testFiles = await scanTestFiles();
50
69
 
51
70
  // Escaneia todos os testes de cada arquivo
52
- console.log("📖 Reading test files to extract test names...");
53
71
  const testsMap = await scanAllTests();
54
72
 
55
73
  // Envia evento de conexão com lista de arquivos e testes
@@ -62,65 +80,48 @@ const websocketHandler = {
62
80
  }
63
81
  }));
64
82
 
65
- console.log(`✓ Found ${testFiles.length} test files with ${Object.values(testsMap).flat().length} tests total`);
83
+ console.log(`${colors.gray}› Found ${testFiles.length} test files with ${Object.values(testsMap).flat().length} tests total${colors.reset}`);
66
84
  },
67
85
  message(ws: any, message: any) {
68
86
  try {
69
87
  const data = JSON.parse(message.toString());
70
- console.log('📨 [WEBSOCKET] Mensagem recebida:', data.type, data.payload);
71
88
 
72
89
  // Processa comandos da UI
73
90
  if (data.type === "run:request") {
74
91
  const file = data.payload?.file;
75
92
  const testName = data.payload?.testName;
76
93
 
77
- console.log('▶️ [RUN REQUEST] file:', file, 'testName:', testName);
78
-
79
94
  if (testName) {
80
- console.log(`Running specific test: ${testName} in ${file}`);
95
+ console.log(`${colors.cyan}▶${colors.reset} Running test: ${colors.gray}${testName}${colors.reset} in ${file}`);
81
96
  } else if (file) {
82
- console.log(`Running file: ${file}`);
97
+ console.log(`${colors.cyan}▶${colors.reset} Running file: ${file}`);
83
98
  } else {
84
- console.log("Running all tests");
99
+ console.log(`${colors.cyan}▶${colors.reset} Running all tests`);
85
100
  }
86
101
 
87
102
  runTests(ws, file, testName);
88
- } else {
89
- console.log('⚠️ [WEBSOCKET] Tipo desconhecido:', data.type);
90
103
  }
91
104
  } catch (err) {
92
105
  console.error("Error processing message:", err);
93
106
  }
94
107
  },
95
108
  close(ws: any) {
96
- console.log("✗ UI disconnected");
109
+ console.log(`${colors.red}✗${colors.reset} UI disconnected`);
97
110
  },
98
111
  };
99
112
 
100
113
  if (isDevMode) {
101
114
  // === MODO DESENVOLVIMENTO ===
102
- // Frontend roda via Vite na porta 5050
103
- // Backend roda separadamente na porta 5060 (apenas WS)
104
-
105
115
  Bun.serve({
106
116
  port: 5060,
107
117
  fetch(req, server) {
108
- // Aceita upgrade em qualquer path ou especificamente /ws
109
- if (server.upgrade(req)) {
110
- return;
111
- }
118
+ if (server.upgrade(req)) return;
112
119
  return new Response("Bun Test UI Backend (Dev Mode)", { status: 200 });
113
120
  },
114
121
  websocket: websocketHandler
115
122
  });
116
-
117
- console.log("📡 WebSocket server running on ws://localhost:5060");
118
-
119
123
  } else {
120
124
  // === MODO PRODUÇÃO ===
121
- // Servidor ÚNICO na porta 5050
122
- // Serve arquivos estáticos do frontend E WebSocket no mesmo endpoint
123
-
124
125
  const PORT = 5050;
125
126
 
126
127
  Bun.serve({
@@ -130,24 +131,18 @@ if (isDevMode) {
130
131
 
131
132
  // 1. WebSocket Upgrade (/ws)
132
133
  if (url.pathname === "/ws") {
133
- if (server.upgrade(req)) {
134
- return;
135
- }
134
+ if (server.upgrade(req)) return;
136
135
  return new Response("WebSocket upgrade failed", { status: 400 });
137
136
  }
138
137
 
139
138
  // 2. Arquivos Estáticos (Frontend)
140
139
  const file = Bun.file(join(distPath, url.pathname === "/" ? "/index.html" : url.pathname));
141
- if (await file.exists()) {
142
- return new Response(file);
143
- }
140
+ if (await file.exists()) return new Response(file);
144
141
 
145
142
  // SPA fallback
146
143
  if (!url.pathname.includes(".")) {
147
144
  const indexFile = Bun.file(join(distPath, "index.html"));
148
- if (await indexFile.exists()) {
149
- return new Response(indexFile);
150
- }
145
+ if (await indexFile.exists()) return new Response(indexFile);
151
146
  }
152
147
 
153
148
  return new Response("Frontend build not found.", { status: 404 });
@@ -155,8 +150,7 @@ if (isDevMode) {
155
150
  websocket: websocketHandler
156
151
  });
157
152
 
158
- console.log(`🚀 Server running on http://localhost:${PORT}`);
159
- console.log(`📡 WebSocket endpoint available at ws://localhost:${PORT}/ws`);
153
+ console.log(`${colors.green}✓${colors.reset} Server running on http://localhost:${PORT}`);
160
154
  }
161
155
 
162
156
 
@@ -281,17 +275,11 @@ function runTests(ws: any, file?: string, testName?: string) {
281
275
  args.push(file);
282
276
  }
283
277
 
284
- // Bun suporta --test-name-pattern para filtrar testes
285
- // Escapa caracteres especiais de regex e usa o nome exato
286
278
  if (testName) {
287
- // Escapa caracteres especiais de regex
288
279
  const escapedName = testName.replace(/[.*+?^${}()|[\\]/g, '\\$&');
289
280
  args.push("--test-name-pattern", escapedName);
290
281
  }
291
282
 
292
- console.log('🚀 [RUN] Comando:', `bun ${args.join(" ")}`);
293
- console.log(`Starting bun test ${args.slice(1).join(" ") || "(all)"}...`);
294
-
295
283
  // Emite evento de início
296
284
  ws.send(JSON.stringify({
297
285
  type: "run:start",
@@ -302,11 +290,9 @@ function runTests(ws: any, file?: string, testName?: string) {
302
290
  }
303
291
  }));
304
292
 
305
- // Spawna o processo bun test
306
- // IMPORTANTE: Não usamos nenhuma API interna do bun:test
307
293
  const bunTest = spawn("bun", args, {
308
294
  cwd: process.cwd(),
309
- env: { ...process.env, FORCE_COLOR: "0" }, // Desabilita cores para facilitar parsing
295
+ env: { ...process.env, FORCE_COLOR: "0" },
310
296
  });
311
297
 
312
298
  let currentTestFile = "";
@@ -348,11 +334,6 @@ function runTests(ws: any, file?: string, testName?: string) {
348
334
  // Função para enviar bloco de erro
349
335
  const flushErrorBlock = () => {
350
336
  if (errorBlock.length > 0) {
351
- console.log('📦 [ERROR BLOCK] Enviando bloco com', errorBlock.length, 'linhas:');
352
- console.log('---START---');
353
- console.log(errorBlock.join('\n'));
354
- console.log('---END---');
355
-
356
337
  ws.send(JSON.stringify({
357
338
  type: "log",
358
339
  payload: { message: errorBlock.join('\n'), stream: "stdout" }
@@ -365,11 +346,6 @@ function runTests(ws: any, file?: string, testName?: string) {
365
346
  // Função para enviar bloco de resumo
366
347
  const flushSummaryBlock = () => {
367
348
  if (summaryBlock.length > 0) {
368
- console.log('📊 [SUMMARY BLOCK] Enviando bloco com', summaryBlock.length, 'linhas:');
369
- console.log('---START---');
370
- console.log(summaryBlock.join('\n'));
371
- console.log('---END---');
372
-
373
349
  ws.send(JSON.stringify({
374
350
  type: "log",
375
351
  payload: { message: summaryBlock.join('\n'), stream: "stdout" }
@@ -384,52 +360,36 @@ function runTests(ws: any, file?: string, testName?: string) {
384
360
  const text = data.toString();
385
361
  buffer += text;
386
362
 
387
- // Processa linhas completas
388
363
  const lines = buffer.split("\n");
389
- buffer = lines.pop() || ""; // Guarda última linha incompleta
364
+ buffer = lines.pop() || "";
390
365
 
391
366
  for (const line of lines) {
392
367
  currentTestFile = processLine(line, ws, currentTestFile);
393
-
394
- // Linhas vazias podem fazer parte de blocos
395
368
  const trimmed = line.trim();
396
369
 
397
- // Verifica se é linha de erro
398
370
  if (isErrorLine(line)) {
399
- console.log('🔴 [ERROR LINE] Detectado:', line.substring(0, 50));
400
- // Se estava no resumo, envia o resumo primeiro
401
371
  flushSummaryBlock();
402
-
403
372
  inErrorBlock = true;
404
373
  errorBlock.push(line);
405
374
  continue;
406
375
  }
407
376
 
408
- // Linha vazia dentro de bloco de erro - mantém no bloco
409
377
  if (inErrorBlock && !trimmed) {
410
- console.log('🔴 [ERROR EMPTY] Linha vazia no bloco de erro');
411
378
  errorBlock.push(line);
412
379
  continue;
413
380
  }
414
381
 
415
- // Verifica se é linha de resumo
416
382
  if (isSummaryLine(line)) {
417
- console.log('📊 [SUMMARY LINE] Detectado:', line.substring(0, 50));
418
- // Se estava no erro, envia o erro primeiro
419
383
  flushErrorBlock();
420
-
421
384
  inSummaryBlock = true;
422
385
  summaryBlock.push(line);
423
386
  continue;
424
387
  }
425
388
 
426
- // Linha normal - envia blocos pendentes e depois a linha
427
389
  flushErrorBlock();
428
390
  flushSummaryBlock();
429
391
 
430
- // Envia linhas normais separadamente (se não vazia)
431
392
  if (trimmed) {
432
- console.log('📝 [NORMAL LINE] Enviando:', line.substring(0, 50));
433
393
  ws.send(JSON.stringify({
434
394
  type: "log",
435
395
  payload: { message: line, stream: "stdout" }
@@ -452,11 +412,8 @@ function runTests(ws: any, file?: string, testName?: string) {
452
412
  });
453
413
 
454
414
  bunTest.on("close", (code) => {
455
- console.log(`bun test exited with code ${code}`);
456
-
457
415
  // Processa buffer pendente antes de finalizar
458
416
  if (buffer.trim()) {
459
- console.log('⚠️ [CLOSE] Buffer pendente:', buffer.substring(0, 100));
460
417
  const lines = buffer.split("\n");
461
418
  for (const line of lines) {
462
419
  if (line.trim()) {
@@ -489,8 +446,6 @@ function runTests(ws: any, file?: string, testName?: string) {
489
446
  flushErrorBlock();
490
447
  flushSummaryBlock();
491
448
 
492
- console.log('✅ [CLOSE] Processo finalizado, todos os logs enviados');
493
-
494
449
  ws.send(JSON.stringify({
495
450
  type: "run:complete",
496
451
  payload: {