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.
- package/cli.ts +78 -70
- package/package.json +1 -1
- 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
|
|
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
|
-
//
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
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
|
|
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(
|
|
128
|
-
console.log(
|
|
129
|
-
console.log(
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
console.log(
|
|
166
|
-
console.log(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
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
|
-
//
|
|
21
|
-
if (import.meta.
|
|
22
|
-
return
|
|
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
|
|
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
|
|
34
|
-
return
|
|
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(
|
|
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(
|
|
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(
|
|
95
|
+
console.log(`${colors.cyan}▶${colors.reset} Running test: ${colors.gray}${testName}${colors.reset} in ${file}`);
|
|
81
96
|
} else if (file) {
|
|
82
|
-
console.log(
|
|
97
|
+
console.log(`${colors.cyan}▶${colors.reset} Running file: ${file}`);
|
|
83
98
|
} else {
|
|
84
|
-
console.log(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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" },
|
|
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() || "";
|
|
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: {
|