@devness/coverit 0.1.0
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/LICENSE +21 -0
- package/README.md +169 -0
- package/dist/agents/orchestrator.d.ts +21 -0
- package/dist/agents/orchestrator.d.ts.map +1 -0
- package/dist/agents/orchestrator.js +235 -0
- package/dist/agents/orchestrator.js.map +1 -0
- package/dist/agents/reporter.d.ts +13 -0
- package/dist/agents/reporter.d.ts.map +1 -0
- package/dist/agents/reporter.js +323 -0
- package/dist/agents/reporter.js.map +1 -0
- package/dist/ai/anthropic-provider.d.ts +19 -0
- package/dist/ai/anthropic-provider.d.ts.map +1 -0
- package/dist/ai/anthropic-provider.js +83 -0
- package/dist/ai/anthropic-provider.js.map +1 -0
- package/dist/ai/claude-cli-provider.d.ts +22 -0
- package/dist/ai/claude-cli-provider.d.ts.map +1 -0
- package/dist/ai/claude-cli-provider.js +197 -0
- package/dist/ai/claude-cli-provider.js.map +1 -0
- package/dist/ai/index.d.ts +15 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +16 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/ollama-provider.d.ts +17 -0
- package/dist/ai/ollama-provider.d.ts.map +1 -0
- package/dist/ai/ollama-provider.js +88 -0
- package/dist/ai/ollama-provider.js.map +1 -0
- package/dist/ai/openai-provider.d.ts +20 -0
- package/dist/ai/openai-provider.d.ts.map +1 -0
- package/dist/ai/openai-provider.js +74 -0
- package/dist/ai/openai-provider.js.map +1 -0
- package/dist/ai/prompts.d.ts +36 -0
- package/dist/ai/prompts.d.ts.map +1 -0
- package/dist/ai/prompts.js +259 -0
- package/dist/ai/prompts.js.map +1 -0
- package/dist/ai/provider-factory.d.ts +26 -0
- package/dist/ai/provider-factory.d.ts.map +1 -0
- package/dist/ai/provider-factory.js +111 -0
- package/dist/ai/provider-factory.js.map +1 -0
- package/dist/ai/types.d.ts +37 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +10 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/analysis/code-scanner.d.ts +9 -0
- package/dist/analysis/code-scanner.d.ts.map +1 -0
- package/dist/analysis/code-scanner.js +409 -0
- package/dist/analysis/code-scanner.js.map +1 -0
- package/dist/analysis/dependency-graph.d.ts +9 -0
- package/dist/analysis/dependency-graph.d.ts.map +1 -0
- package/dist/analysis/dependency-graph.js +149 -0
- package/dist/analysis/dependency-graph.js.map +1 -0
- package/dist/analysis/diff-analyzer.d.ts +9 -0
- package/dist/analysis/diff-analyzer.d.ts.map +1 -0
- package/dist/analysis/diff-analyzer.js +232 -0
- package/dist/analysis/diff-analyzer.js.map +1 -0
- package/dist/analysis/index.d.ts +5 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +5 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/analysis/strategy-planner.d.ts +11 -0
- package/dist/analysis/strategy-planner.d.ts.map +1 -0
- package/dist/analysis/strategy-planner.js +384 -0
- package/dist/analysis/strategy-planner.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +288 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/executors/base-executor.d.ts +35 -0
- package/dist/executors/base-executor.d.ts.map +1 -0
- package/dist/executors/base-executor.js +138 -0
- package/dist/executors/base-executor.js.map +1 -0
- package/dist/executors/browser-runner.d.ts +24 -0
- package/dist/executors/browser-runner.d.ts.map +1 -0
- package/dist/executors/browser-runner.js +194 -0
- package/dist/executors/browser-runner.js.map +1 -0
- package/dist/executors/cloud-runner.d.ts +41 -0
- package/dist/executors/cloud-runner.d.ts.map +1 -0
- package/dist/executors/cloud-runner.js +153 -0
- package/dist/executors/cloud-runner.js.map +1 -0
- package/dist/executors/index.d.ts +12 -0
- package/dist/executors/index.d.ts.map +1 -0
- package/dist/executors/index.js +28 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/executors/local-runner.d.ts +40 -0
- package/dist/executors/local-runner.d.ts.map +1 -0
- package/dist/executors/local-runner.js +395 -0
- package/dist/executors/local-runner.js.map +1 -0
- package/dist/executors/reporter.d.ts +6 -0
- package/dist/executors/reporter.d.ts.map +1 -0
- package/dist/executors/reporter.js +6 -0
- package/dist/executors/reporter.js.map +1 -0
- package/dist/executors/simulator-runner.d.ts +30 -0
- package/dist/executors/simulator-runner.d.ts.map +1 -0
- package/dist/executors/simulator-runner.js +339 -0
- package/dist/executors/simulator-runner.js.map +1 -0
- package/dist/generators/api-test.d.ts +22 -0
- package/dist/generators/api-test.d.ts.map +1 -0
- package/dist/generators/api-test.js +235 -0
- package/dist/generators/api-test.js.map +1 -0
- package/dist/generators/base-generator.d.ts +79 -0
- package/dist/generators/base-generator.d.ts.map +1 -0
- package/dist/generators/base-generator.js +234 -0
- package/dist/generators/base-generator.js.map +1 -0
- package/dist/generators/desktop-test.d.ts +22 -0
- package/dist/generators/desktop-test.d.ts.map +1 -0
- package/dist/generators/desktop-test.js +290 -0
- package/dist/generators/desktop-test.js.map +1 -0
- package/dist/generators/e2e-browser.d.ts +19 -0
- package/dist/generators/e2e-browser.d.ts.map +1 -0
- package/dist/generators/e2e-browser.js +233 -0
- package/dist/generators/e2e-browser.js.map +1 -0
- package/dist/generators/index.d.ts +21 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +66 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/mobile-test.d.ts +22 -0
- package/dist/generators/mobile-test.d.ts.map +1 -0
- package/dist/generators/mobile-test.js +286 -0
- package/dist/generators/mobile-test.js.map +1 -0
- package/dist/generators/unit-test.d.ts +23 -0
- package/dist/generators/unit-test.d.ts.map +1 -0
- package/dist/generators/unit-test.js +282 -0
- package/dist/generators/unit-test.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +8 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +217 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/types/index.d.ts +295 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/framework-detector.d.ts +28 -0
- package/dist/utils/framework-detector.d.ts.map +1 -0
- package/dist/utils/framework-detector.js +184 -0
- package/dist/utils/framework-detector.js.map +1 -0
- package/dist/utils/git.d.ts +33 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +82 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/logger.d.ts +17 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +47 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simulator Runner — Execute tests on mobile simulators and desktop app shells.
|
|
3
|
+
*
|
|
4
|
+
* Supports three targets:
|
|
5
|
+
* - iOS Simulator via `xcrun simctl` + Detox
|
|
6
|
+
* - Android Emulator via `emulator` CLI + Detox
|
|
7
|
+
* - Tauri desktop via `cargo tauri dev` + WebDriver
|
|
8
|
+
*
|
|
9
|
+
* Each path checks for tool availability before attempting execution
|
|
10
|
+
* and returns meaningful errors when the required toolchain is missing.
|
|
11
|
+
*/
|
|
12
|
+
import { spawn } from "node:child_process";
|
|
13
|
+
import { existsSync } from "node:fs";
|
|
14
|
+
import { dirname, resolve, join } from "node:path";
|
|
15
|
+
import { BaseExecutor } from "./base-executor.js";
|
|
16
|
+
export class SimulatorRunner extends BaseExecutor {
|
|
17
|
+
async execute(test, config) {
|
|
18
|
+
const result = this.createBaseResult(test.planId);
|
|
19
|
+
const start = Date.now();
|
|
20
|
+
try {
|
|
21
|
+
// Route to the correct simulator based on test type
|
|
22
|
+
switch (test.testType) {
|
|
23
|
+
case "e2e-mobile":
|
|
24
|
+
return await this.withTimeout(this.executeMobile(test, config, result), config.timeout);
|
|
25
|
+
case "e2e-desktop":
|
|
26
|
+
return await this.withTimeout(this.executeDesktop(test, config, result), config.timeout);
|
|
27
|
+
default:
|
|
28
|
+
result.status = "error";
|
|
29
|
+
result.output = `SimulatorRunner does not support test type: ${test.testType}. Expected e2e-mobile or e2e-desktop.`;
|
|
30
|
+
result.duration = Date.now() - start;
|
|
31
|
+
result.failures.push({
|
|
32
|
+
testName: "(simulator-runner)",
|
|
33
|
+
message: result.output,
|
|
34
|
+
});
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
result.duration = Date.now() - start;
|
|
40
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
41
|
+
if (message.includes("timed out")) {
|
|
42
|
+
result.status = "timeout";
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
result.status = "error";
|
|
46
|
+
}
|
|
47
|
+
result.output = message;
|
|
48
|
+
result.failures.push({ testName: "(simulator-runner)", message });
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// ── Mobile (iOS / Android) ────────────────────────────────────
|
|
53
|
+
async executeMobile(test, config, result) {
|
|
54
|
+
const start = Date.now();
|
|
55
|
+
const platform = this.detectMobilePlatform();
|
|
56
|
+
if (platform === "ios") {
|
|
57
|
+
return this.executeIOS(test, config, result, start);
|
|
58
|
+
}
|
|
59
|
+
else if (platform === "android") {
|
|
60
|
+
return this.executeAndroid(test, config, result, start);
|
|
61
|
+
}
|
|
62
|
+
result.duration = Date.now() - start;
|
|
63
|
+
result.status = "error";
|
|
64
|
+
result.output =
|
|
65
|
+
"No mobile simulator available. " +
|
|
66
|
+
"iOS: requires Xcode with `xcrun simctl`. " +
|
|
67
|
+
"Android: requires Android SDK with `emulator` CLI.";
|
|
68
|
+
result.failures.push({
|
|
69
|
+
testName: "(mobile-simulator)",
|
|
70
|
+
message: result.output,
|
|
71
|
+
});
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
async executeIOS(test, _config, result, start) {
|
|
75
|
+
// Check for booted simulator
|
|
76
|
+
const devices = await this.exec("xcrun", [
|
|
77
|
+
"simctl",
|
|
78
|
+
"list",
|
|
79
|
+
"devices",
|
|
80
|
+
"--json",
|
|
81
|
+
]);
|
|
82
|
+
const deviceJson = this.parseJsonOutput(devices.stdout);
|
|
83
|
+
const bootedDevice = this.findBootedIOSDevice(deviceJson);
|
|
84
|
+
if (!bootedDevice) {
|
|
85
|
+
// Try to boot the first available iPhone simulator
|
|
86
|
+
const availableDevice = this.findAvailableIOSDevice(deviceJson);
|
|
87
|
+
if (availableDevice) {
|
|
88
|
+
await this.exec("xcrun", ["simctl", "boot", availableDevice]);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
result.duration = Date.now() - start;
|
|
92
|
+
result.status = "error";
|
|
93
|
+
result.output = "No iOS simulator device available. Create one in Xcode.";
|
|
94
|
+
result.failures.push({
|
|
95
|
+
testName: "(ios-simulator)",
|
|
96
|
+
message: result.output,
|
|
97
|
+
});
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Run Detox tests
|
|
102
|
+
const cwd = this.findProjectRoot(test.filePath);
|
|
103
|
+
const detoxResult = await this.exec("bunx", ["detox", "test", "--configuration", "ios.sim.debug", test.filePath], cwd);
|
|
104
|
+
result.duration = Date.now() - start;
|
|
105
|
+
result.output = this.combineOutput(detoxResult.stdout, detoxResult.stderr);
|
|
106
|
+
// Detox doesn't have a standard JSON reporter — parse exit code
|
|
107
|
+
if (detoxResult.exitCode === 0) {
|
|
108
|
+
result.status = "passed";
|
|
109
|
+
result.totalTests = test.testCount;
|
|
110
|
+
result.passed = test.testCount;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
result.status = "failed";
|
|
114
|
+
result.totalTests = test.testCount;
|
|
115
|
+
result.failures.push({
|
|
116
|
+
testName: "(detox-ios)",
|
|
117
|
+
message: detoxResult.stderr.slice(0, 2000) || "Detox test failed",
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
async executeAndroid(test, _config, result, start) {
|
|
123
|
+
// List available AVDs
|
|
124
|
+
const avdResult = await this.exec("emulator", ["-list-avds"]);
|
|
125
|
+
const avds = avdResult.stdout.trim().split("\n").filter(Boolean);
|
|
126
|
+
if (avds.length === 0) {
|
|
127
|
+
result.duration = Date.now() - start;
|
|
128
|
+
result.status = "error";
|
|
129
|
+
result.output =
|
|
130
|
+
"No Android AVD available. Create one with Android Studio's AVD Manager.";
|
|
131
|
+
result.failures.push({
|
|
132
|
+
testName: "(android-emulator)",
|
|
133
|
+
message: result.output,
|
|
134
|
+
});
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
// Check if emulator is already running via adb
|
|
138
|
+
const adbResult = await this.exec("adb", ["devices"]);
|
|
139
|
+
const hasRunningEmulator = adbResult.stdout.includes("emulator-");
|
|
140
|
+
if (!hasRunningEmulator) {
|
|
141
|
+
// Start the first available AVD in the background (don't wait for it)
|
|
142
|
+
// Detox will handle waiting for the emulator to boot
|
|
143
|
+
this.execBackground("emulator", ["-avd", avds[0], "-no-window"]);
|
|
144
|
+
// Give the emulator a moment to begin booting
|
|
145
|
+
await new Promise((r) => setTimeout(r, 5000));
|
|
146
|
+
}
|
|
147
|
+
// Run Detox tests
|
|
148
|
+
const cwd = this.findProjectRoot(test.filePath);
|
|
149
|
+
const detoxResult = await this.exec("bunx", [
|
|
150
|
+
"detox",
|
|
151
|
+
"test",
|
|
152
|
+
"--configuration",
|
|
153
|
+
"android.emu.debug",
|
|
154
|
+
test.filePath,
|
|
155
|
+
], cwd);
|
|
156
|
+
result.duration = Date.now() - start;
|
|
157
|
+
result.output = this.combineOutput(detoxResult.stdout, detoxResult.stderr);
|
|
158
|
+
if (detoxResult.exitCode === 0) {
|
|
159
|
+
result.status = "passed";
|
|
160
|
+
result.totalTests = test.testCount;
|
|
161
|
+
result.passed = test.testCount;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
result.status = "failed";
|
|
165
|
+
result.totalTests = test.testCount;
|
|
166
|
+
result.failures.push({
|
|
167
|
+
testName: "(detox-android)",
|
|
168
|
+
message: detoxResult.stderr.slice(0, 2000) || "Detox test failed",
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
// ── Desktop (Tauri) ───────────────────────────────────────────
|
|
174
|
+
async executeDesktop(test, _config, result) {
|
|
175
|
+
const start = Date.now();
|
|
176
|
+
// Check for Tauri CLI
|
|
177
|
+
const hasCargo = await this.isCommandAvailable("cargo");
|
|
178
|
+
if (!hasCargo) {
|
|
179
|
+
result.duration = Date.now() - start;
|
|
180
|
+
result.status = "error";
|
|
181
|
+
result.output =
|
|
182
|
+
"Tauri testing requires Rust and cargo. Install from https://rustup.rs/";
|
|
183
|
+
result.failures.push({
|
|
184
|
+
testName: "(tauri-desktop)",
|
|
185
|
+
message: result.output,
|
|
186
|
+
});
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
const cwd = this.findProjectRoot(test.filePath);
|
|
190
|
+
// Check for tauri.conf.json to confirm this is a Tauri project
|
|
191
|
+
const hasTauriConfig = existsSync(join(cwd, "src-tauri", "tauri.conf.json")) ||
|
|
192
|
+
existsSync(join(cwd, "src-tauri", "Cargo.toml"));
|
|
193
|
+
if (!hasTauriConfig) {
|
|
194
|
+
result.duration = Date.now() - start;
|
|
195
|
+
result.status = "error";
|
|
196
|
+
result.output =
|
|
197
|
+
"No Tauri configuration found (src-tauri/tauri.conf.json). Is this a Tauri project?";
|
|
198
|
+
result.failures.push({
|
|
199
|
+
testName: "(tauri-desktop)",
|
|
200
|
+
message: result.output,
|
|
201
|
+
});
|
|
202
|
+
return result;
|
|
203
|
+
}
|
|
204
|
+
// Run WebDriver-based tests via Playwright against the Tauri window
|
|
205
|
+
// The test file should use @playwright/test with electron/tauri helpers
|
|
206
|
+
const testResult = await this.exec("bunx", ["playwright", "test", test.filePath, "--reporter=json"], cwd);
|
|
207
|
+
result.duration = Date.now() - start;
|
|
208
|
+
result.output = this.combineOutput(testResult.stdout, testResult.stderr);
|
|
209
|
+
// Parse Playwright JSON output
|
|
210
|
+
const json = this.parseJsonOutput(testResult.stdout);
|
|
211
|
+
if (json?.stats) {
|
|
212
|
+
result.passed = json.stats.expected ?? 0;
|
|
213
|
+
result.failed = json.stats.unexpected ?? 0;
|
|
214
|
+
result.skipped = json.stats.skipped ?? 0;
|
|
215
|
+
result.totalTests = result.passed + result.failed + result.skipped;
|
|
216
|
+
result.status =
|
|
217
|
+
testResult.exitCode === 0 && result.failed === 0 ? "passed" : "failed";
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
result.status = testResult.exitCode === 0 ? "passed" : "failed";
|
|
221
|
+
result.totalTests = test.testCount;
|
|
222
|
+
if (testResult.exitCode === 0) {
|
|
223
|
+
result.passed = test.testCount;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
// ── Tool Detection ────────────────────────────────────────────
|
|
229
|
+
detectMobilePlatform() {
|
|
230
|
+
// Prefer iOS on macOS since xcrun is likely available
|
|
231
|
+
try {
|
|
232
|
+
if (process.platform === "darwin") {
|
|
233
|
+
return "ios";
|
|
234
|
+
}
|
|
235
|
+
return "android";
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
findBootedIOSDevice(deviceJson) {
|
|
242
|
+
if (!deviceJson?.devices)
|
|
243
|
+
return null;
|
|
244
|
+
for (const runtime of Object.values(deviceJson.devices)) {
|
|
245
|
+
if (!Array.isArray(runtime))
|
|
246
|
+
continue;
|
|
247
|
+
for (const device of runtime) {
|
|
248
|
+
if (device.state === "Booted" && device.isAvailable) {
|
|
249
|
+
return device.udid;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
findAvailableIOSDevice(deviceJson) {
|
|
256
|
+
if (!deviceJson?.devices)
|
|
257
|
+
return null;
|
|
258
|
+
for (const [runtime, devices] of Object.entries(deviceJson.devices)) {
|
|
259
|
+
if (!runtime.includes("iOS") || !Array.isArray(devices))
|
|
260
|
+
continue;
|
|
261
|
+
for (const device of devices) {
|
|
262
|
+
if (device.isAvailable &&
|
|
263
|
+
device.name?.includes("iPhone")) {
|
|
264
|
+
return device.udid;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
async isCommandAvailable(cmd) {
|
|
271
|
+
try {
|
|
272
|
+
const result = await this.exec("which", [cmd]);
|
|
273
|
+
return result.exitCode === 0;
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// ── Process Helpers ───────────────────────────────────────────
|
|
280
|
+
exec(cmd, args, cwd) {
|
|
281
|
+
return new Promise((resolve, reject) => {
|
|
282
|
+
let child;
|
|
283
|
+
try {
|
|
284
|
+
child = spawn(cmd, args, {
|
|
285
|
+
cwd,
|
|
286
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
287
|
+
env: { ...process.env, CI: "true", FORCE_COLOR: "0" },
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
catch (err) {
|
|
291
|
+
reject(new Error(`Failed to spawn ${cmd}: ${err instanceof Error ? err.message : String(err)}`));
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
const stdoutChunks = [];
|
|
295
|
+
const stderrChunks = [];
|
|
296
|
+
child.stdout?.on("data", (chunk) => stdoutChunks.push(chunk));
|
|
297
|
+
child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
|
|
298
|
+
child.on("error", (err) => reject(new Error(`${cmd} error: ${err.message}`)));
|
|
299
|
+
child.on("close", (code) => {
|
|
300
|
+
resolve({
|
|
301
|
+
exitCode: code ?? 1,
|
|
302
|
+
stdout: Buffer.concat(stdoutChunks).toString("utf-8"),
|
|
303
|
+
stderr: Buffer.concat(stderrChunks).toString("utf-8"),
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
/** Fire-and-forget process for background tasks like starting an emulator. */
|
|
309
|
+
execBackground(cmd, args) {
|
|
310
|
+
try {
|
|
311
|
+
const child = spawn(cmd, args, {
|
|
312
|
+
stdio: "ignore",
|
|
313
|
+
detached: true,
|
|
314
|
+
});
|
|
315
|
+
child.unref();
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
// Best-effort — the actual test run will fail if the emulator doesn't start
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
findProjectRoot(filePath) {
|
|
322
|
+
let dir = dirname(resolve(filePath));
|
|
323
|
+
while (dir !== "/" && dir !== ".") {
|
|
324
|
+
if (existsSync(join(dir, "package.json")))
|
|
325
|
+
return dir;
|
|
326
|
+
dir = dirname(dir);
|
|
327
|
+
}
|
|
328
|
+
return dirname(resolve(filePath));
|
|
329
|
+
}
|
|
330
|
+
combineOutput(stdout, stderr) {
|
|
331
|
+
const parts = [];
|
|
332
|
+
if (stdout)
|
|
333
|
+
parts.push(stdout);
|
|
334
|
+
if (stderr)
|
|
335
|
+
parts.push(`[stderr]\n${stderr}`);
|
|
336
|
+
return parts.join("\n").slice(0, 50_000);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=simulator-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simulator-runner.js","sourceRoot":"","sources":["../../src/executors/simulator-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GeneratorContext, GeneratorResult } from "../types/index.js";
|
|
2
|
+
import { BaseGenerator } from "./base-generator.js";
|
|
3
|
+
/**
|
|
4
|
+
* Generates API integration tests for HTTP endpoints.
|
|
5
|
+
* Supports Hono (app.request), Express/NestJS (supertest), and Fastify patterns.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ApiTestGenerator extends BaseGenerator {
|
|
8
|
+
generate(context: GeneratorContext): Promise<GeneratorResult>;
|
|
9
|
+
private buildApiImports;
|
|
10
|
+
private generateEndpointTests;
|
|
11
|
+
private successCase;
|
|
12
|
+
private validationErrorCase;
|
|
13
|
+
private unauthorizedCase;
|
|
14
|
+
private notFoundCase;
|
|
15
|
+
private buildRequestCall;
|
|
16
|
+
private honoRequestCall;
|
|
17
|
+
private supertestRequestCall;
|
|
18
|
+
private hasAuthMiddleware;
|
|
19
|
+
private sampleRequestBody;
|
|
20
|
+
private relativeImportPath;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=api-test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-test.d.ts","sourceRoot":"","sources":["../../src/generators/api-test.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAKV,gBAAgB,EAChB,eAAe,EAGhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,aAAa;IAC3C,QAAQ,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IA0GnE,OAAO,CAAC,eAAe;IA6BvB,OAAO,CAAC,qBAAqB;IA4B7B,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,mBAAmB;IAc3B,OAAO,CAAC,gBAAgB;IAexB,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,eAAe;IA2BvB,OAAO,CAAC,oBAAoB;IA6B5B,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,iBAAiB;IAoBzB,OAAO,CAAC,kBAAkB;CAK3B"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// Generated by coverit — https://coverit.dev
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, relative } from "node:path";
|
|
4
|
+
import { BaseGenerator } from "./base-generator.js";
|
|
5
|
+
/**
|
|
6
|
+
* Generates API integration tests for HTTP endpoints.
|
|
7
|
+
* Supports Hono (app.request), Express/NestJS (supertest), and Fastify patterns.
|
|
8
|
+
*/
|
|
9
|
+
export class ApiTestGenerator extends BaseGenerator {
|
|
10
|
+
async generate(context) {
|
|
11
|
+
const { plan, project, scanResults, existingTests } = context;
|
|
12
|
+
const tests = [];
|
|
13
|
+
const warnings = [];
|
|
14
|
+
const skipped = [];
|
|
15
|
+
for (const scan of scanResults) {
|
|
16
|
+
if (!plan.target.files.includes(scan.file))
|
|
17
|
+
continue;
|
|
18
|
+
// ── AI-powered generation (preferred path) ──────────────
|
|
19
|
+
if (this.aiProvider) {
|
|
20
|
+
try {
|
|
21
|
+
const sourceCode = await readFile(join(project.root, scan.file), "utf-8");
|
|
22
|
+
const aiResult = await this.generateWithAI({
|
|
23
|
+
sourceCode,
|
|
24
|
+
scanResult: scan,
|
|
25
|
+
testType: "api",
|
|
26
|
+
framework: project.testFramework,
|
|
27
|
+
existingTests,
|
|
28
|
+
});
|
|
29
|
+
if (aiResult) {
|
|
30
|
+
const testFileName = this.generateTestFileName(scan.file, "api");
|
|
31
|
+
tests.push({
|
|
32
|
+
planId: plan.id,
|
|
33
|
+
filePath: testFileName,
|
|
34
|
+
content: aiResult,
|
|
35
|
+
testType: "api",
|
|
36
|
+
testCount: this.countTestCases(aiResult),
|
|
37
|
+
framework: project.testFramework === "playwright" ||
|
|
38
|
+
project.testFramework === "detox"
|
|
39
|
+
? "vitest"
|
|
40
|
+
: project.testFramework,
|
|
41
|
+
});
|
|
42
|
+
continue; // Skip template fallback for this file
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Fall through to template-based generation
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// ── Template-based generation (fallback) ────────────────
|
|
50
|
+
const endpoints = scan.endpoints;
|
|
51
|
+
if (endpoints.length === 0) {
|
|
52
|
+
skipped.push({
|
|
53
|
+
target: scan.file,
|
|
54
|
+
reason: "No endpoints detected",
|
|
55
|
+
});
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const testFileName = this.generateTestFileName(scan.file, "api");
|
|
59
|
+
const fw = project.testFramework;
|
|
60
|
+
const framework = project.framework;
|
|
61
|
+
const imports = this.buildApiImports(scan, fw, framework, testFileName);
|
|
62
|
+
const bodyBlocks = [];
|
|
63
|
+
let testCount = 0;
|
|
64
|
+
for (const endpoint of endpoints) {
|
|
65
|
+
const endpointLabel = `${endpoint.method} ${endpoint.path}`;
|
|
66
|
+
if (this.isAlreadyTested(endpoint.handler, existingTests)) {
|
|
67
|
+
skipped.push({
|
|
68
|
+
target: endpointLabel,
|
|
69
|
+
reason: "Already has tests",
|
|
70
|
+
});
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const cases = this.generateEndpointTests(endpoint, framework, fw);
|
|
74
|
+
bodyBlocks.push(this.buildDescribeBlock(endpointLabel, cases));
|
|
75
|
+
testCount += cases.length;
|
|
76
|
+
}
|
|
77
|
+
if (testCount === 0)
|
|
78
|
+
continue;
|
|
79
|
+
const content = this.assembleTestFile({
|
|
80
|
+
imports,
|
|
81
|
+
body: bodyBlocks,
|
|
82
|
+
});
|
|
83
|
+
tests.push({
|
|
84
|
+
planId: plan.id,
|
|
85
|
+
filePath: testFileName,
|
|
86
|
+
content,
|
|
87
|
+
testType: "api",
|
|
88
|
+
testCount,
|
|
89
|
+
framework: fw === "playwright" || fw === "detox" ? "vitest" : fw,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
return { tests, warnings, skipped };
|
|
93
|
+
}
|
|
94
|
+
// ── Import generation ──────────────────────────────────────
|
|
95
|
+
buildApiImports(scan, fw, framework, testFilePath) {
|
|
96
|
+
const lines = [this.buildImports(fw)];
|
|
97
|
+
const sourcePath = this.relativeImportPath(testFilePath, scan.file);
|
|
98
|
+
switch (framework) {
|
|
99
|
+
case "hono":
|
|
100
|
+
lines.push(`import app from '${sourcePath}';`);
|
|
101
|
+
break;
|
|
102
|
+
case "express":
|
|
103
|
+
case "nestjs":
|
|
104
|
+
case "fastify":
|
|
105
|
+
lines.push("import request from 'supertest';");
|
|
106
|
+
lines.push(`import app from '${sourcePath}';`);
|
|
107
|
+
break;
|
|
108
|
+
default:
|
|
109
|
+
lines.push("import request from 'supertest';");
|
|
110
|
+
lines.push(`import app from '${sourcePath}';`);
|
|
111
|
+
}
|
|
112
|
+
return lines;
|
|
113
|
+
}
|
|
114
|
+
// ── Endpoint test generation ───────────────────────────────
|
|
115
|
+
generateEndpointTests(endpoint, framework, _fw) {
|
|
116
|
+
const cases = [];
|
|
117
|
+
// 200/201 success
|
|
118
|
+
cases.push(this.successCase(endpoint, framework));
|
|
119
|
+
// 400 validation error (only for POST/PUT/PATCH with body)
|
|
120
|
+
if (["POST", "PUT", "PATCH"].includes(endpoint.method)) {
|
|
121
|
+
cases.push(this.validationErrorCase(endpoint, framework));
|
|
122
|
+
}
|
|
123
|
+
// 401 unauthorized (if auth middleware detected)
|
|
124
|
+
if (this.hasAuthMiddleware(endpoint)) {
|
|
125
|
+
cases.push(this.unauthorizedCase(endpoint, framework));
|
|
126
|
+
}
|
|
127
|
+
// 404 not found (for endpoints with path params)
|
|
128
|
+
if (endpoint.path.includes(":") || endpoint.path.includes("{")) {
|
|
129
|
+
cases.push(this.notFoundCase(endpoint, framework));
|
|
130
|
+
}
|
|
131
|
+
return cases;
|
|
132
|
+
}
|
|
133
|
+
successCase(endpoint, framework) {
|
|
134
|
+
const expectedStatus = endpoint.method === "POST" ? 201 : 200;
|
|
135
|
+
const body = this.buildRequestCall(endpoint, framework, expectedStatus);
|
|
136
|
+
const name = `should return ${expectedStatus} on success`;
|
|
137
|
+
return this.buildAsyncTestCase(name, body);
|
|
138
|
+
}
|
|
139
|
+
validationErrorCase(endpoint, framework) {
|
|
140
|
+
const body = this.buildRequestCall(endpoint, framework, 400, "{}" // empty body to trigger validation error
|
|
141
|
+
);
|
|
142
|
+
const name = "should return 400 for invalid request body";
|
|
143
|
+
return this.buildAsyncTestCase(name, body);
|
|
144
|
+
}
|
|
145
|
+
unauthorizedCase(endpoint, framework) {
|
|
146
|
+
const body = this.buildRequestCall(endpoint, framework, 401, undefined, false // no auth header
|
|
147
|
+
);
|
|
148
|
+
const name = "should return 401 without authentication";
|
|
149
|
+
return this.buildAsyncTestCase(name, body);
|
|
150
|
+
}
|
|
151
|
+
notFoundCase(endpoint, framework) {
|
|
152
|
+
// Replace path params with non-existent IDs
|
|
153
|
+
const path = endpoint.path
|
|
154
|
+
.replace(/:(\w+)/g, "non-existent-id")
|
|
155
|
+
.replace(/\{(\w+)\}/g, "non-existent-id");
|
|
156
|
+
const modifiedEndpoint = { ...endpoint, path };
|
|
157
|
+
const body = this.buildRequestCall(modifiedEndpoint, framework, 404);
|
|
158
|
+
const name = "should return 404 for non-existent resource";
|
|
159
|
+
return this.buildAsyncTestCase(name, body);
|
|
160
|
+
}
|
|
161
|
+
// ── Request builders per framework ─────────────────────────
|
|
162
|
+
buildRequestCall(endpoint, framework, expectedStatus, overrideBody, includeAuth = true) {
|
|
163
|
+
const method = endpoint.method.toLowerCase();
|
|
164
|
+
const path = endpoint.path;
|
|
165
|
+
const hasBody = ["post", "put", "patch"].includes(method);
|
|
166
|
+
const sampleBody = overrideBody ?? this.sampleRequestBody(endpoint);
|
|
167
|
+
if (framework === "hono") {
|
|
168
|
+
return this.honoRequestCall(method, path, expectedStatus, hasBody ? sampleBody : undefined, includeAuth);
|
|
169
|
+
}
|
|
170
|
+
// Express / NestJS / Fastify — supertest
|
|
171
|
+
return this.supertestRequestCall(method, path, expectedStatus, hasBody ? sampleBody : undefined, includeAuth);
|
|
172
|
+
}
|
|
173
|
+
honoRequestCall(method, path, expectedStatus, body, includeAuth = true) {
|
|
174
|
+
const headers = [];
|
|
175
|
+
if (body)
|
|
176
|
+
headers.push("'Content-Type': 'application/json'");
|
|
177
|
+
if (includeAuth)
|
|
178
|
+
headers.push("'Authorization': 'Bearer test-token'");
|
|
179
|
+
const headerStr = headers.length > 0 ? `, headers: { ${headers.join(", ")} }` : "";
|
|
180
|
+
const bodyStr = body ? `, body: JSON.stringify(${body})` : "";
|
|
181
|
+
const lines = [
|
|
182
|
+
`const res = await app.request('${path}', { method: '${method.toUpperCase()}'${bodyStr}${headerStr} });`,
|
|
183
|
+
`expect(res.status).toBe(${expectedStatus});`,
|
|
184
|
+
];
|
|
185
|
+
if (expectedStatus < 300) {
|
|
186
|
+
lines.push(`const data = await res.json();`);
|
|
187
|
+
lines.push(`expect(data).toBeDefined();`);
|
|
188
|
+
}
|
|
189
|
+
return lines.join("\n");
|
|
190
|
+
}
|
|
191
|
+
supertestRequestCall(method, path, expectedStatus, body, includeAuth = true) {
|
|
192
|
+
const lines = [`const res = await request(app)`];
|
|
193
|
+
lines.push(` .${method}('${path}')`);
|
|
194
|
+
if (includeAuth) {
|
|
195
|
+
lines.push(` .set('Authorization', 'Bearer test-token')`);
|
|
196
|
+
}
|
|
197
|
+
if (body) {
|
|
198
|
+
lines.push(` .send(${body})`);
|
|
199
|
+
}
|
|
200
|
+
lines.push(` .expect(${expectedStatus});`);
|
|
201
|
+
if (expectedStatus < 300) {
|
|
202
|
+
lines.push(`expect(res.body).toBeDefined();`);
|
|
203
|
+
}
|
|
204
|
+
return lines.join("\n");
|
|
205
|
+
}
|
|
206
|
+
// ── Helpers ────────────────────────────────────────────────
|
|
207
|
+
hasAuthMiddleware(endpoint) {
|
|
208
|
+
return endpoint.middleware.some((m) => m.toLowerCase().includes("auth") ||
|
|
209
|
+
m.toLowerCase().includes("guard") ||
|
|
210
|
+
m.toLowerCase().includes("protect"));
|
|
211
|
+
}
|
|
212
|
+
sampleRequestBody(endpoint) {
|
|
213
|
+
// Produce a minimal plausible JSON body based on endpoint path heuristics
|
|
214
|
+
const path = endpoint.path.toLowerCase();
|
|
215
|
+
if (path.includes("login") || path.includes("auth")) {
|
|
216
|
+
return `{ email: 'test@example.com', password: 'password123' }`;
|
|
217
|
+
}
|
|
218
|
+
if (path.includes("user")) {
|
|
219
|
+
return `{ name: 'Test User', email: 'user@example.com' }`;
|
|
220
|
+
}
|
|
221
|
+
if (path.includes("post") || path.includes("article")) {
|
|
222
|
+
return `{ title: 'Test Title', content: 'Test content body' }`;
|
|
223
|
+
}
|
|
224
|
+
if (path.includes("comment")) {
|
|
225
|
+
return `{ body: 'Test comment' }`;
|
|
226
|
+
}
|
|
227
|
+
return `{ name: 'test', value: 'test-value' }`;
|
|
228
|
+
}
|
|
229
|
+
relativeImportPath(from, to) {
|
|
230
|
+
const rel = relative(dirname(from), to);
|
|
231
|
+
const withoutExt = rel.replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
232
|
+
return rel.startsWith(".") ? withoutExt : `./${withoutExt}`;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=api-test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-test.js","sourceRoot":"","sources":["../../src/generators/api-test.ts"],"names":[],"mappings":"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"}
|