@empiricalrun/test-gen 0.69.0 → 0.69.1
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/CHANGELOG.md +8 -0
- package/dist/agent/cua/pw-codegen/pw-pause/index.d.ts.map +1 -1
- package/dist/agent/cua/pw-codegen/pw-pause/index.js +5 -4
- package/dist/auth/api-client.d.ts +1 -1
- package/dist/auth/api-client.d.ts.map +1 -1
- package/dist/auth/cli-auth.js +1 -1
- package/dist/bin/index.js +0 -2
- package/dist/bin/utils/index.js +1 -1
- package/dist/file/server.d.ts.map +1 -1
- package/dist/file/server.js +56 -0
- package/dist/index.js +1 -1
- package/dist/recorder/index.d.ts.map +1 -1
- package/dist/recorder/index.js +12 -6
- package/dist/recorder/request.d.ts.map +1 -1
- package/dist/recorder/request.js +156 -5
- package/dist/recorder/temp-files.d.ts +1 -1
- package/dist/recorder/temp-files.d.ts.map +1 -1
- package/dist/recorder/temp-files.js +2 -3
- package/package.json +2 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/recorder/display.d.ts +0 -2
- package/dist/recorder/display.d.ts.map +0 -1
- package/dist/recorder/display.js +0 -50
package/CHANGELOG.md
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAKjD,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE9E,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,oBAyCvD;AAED,qBAAa,sBAAuB,YAAW,qBAAqB;IAClE,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,iBAAiB,CAAqB;;YAMhC,QAAQ;IAUhB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrC,sBAAsB,CAAC,IAAI,EAAE,IAAI;IAyBjC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAU9C"}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.PlaywrightPauseCodegen = exports.revertToOriginalPwCode = exports.preparePlaywrightForCodegen = void 0;
|
|
7
7
|
exports.canUsePauseCodegen = canUsePauseCodegen;
|
|
8
8
|
const express_1 = __importDefault(require("express"));
|
|
9
|
+
const logger_1 = require("../../../../logger");
|
|
9
10
|
const ipc_1 = require("./ipc");
|
|
10
11
|
const patch_1 = require("./patch");
|
|
11
12
|
var patch_2 = require("./patch");
|
|
@@ -16,12 +17,12 @@ async function canUsePauseCodegen(repoDir) {
|
|
|
16
17
|
if (!hasPatchedPwCode) {
|
|
17
18
|
// This codegen approach requires patching the playwright code to setup an
|
|
18
19
|
// IPC server <> client that passes generated code from Playwright to @empiricalrun/test-gen
|
|
19
|
-
|
|
20
|
+
logger_1.logger.error("Cannot use pause codegen because recorder app is not patched");
|
|
20
21
|
return false;
|
|
21
22
|
}
|
|
22
23
|
if (!(await (0, ipc_1.isIPCPortAvailable)())) {
|
|
23
24
|
// The IPC port is hardcoded, and it should be available for IPC to work
|
|
24
|
-
|
|
25
|
+
logger_1.logger.error("Cannot use pause codegen because IPC port is not available");
|
|
25
26
|
return false;
|
|
26
27
|
}
|
|
27
28
|
const isRunningHeaded = process.env.RUN_PLAYWRIGHT_HEADED &&
|
|
@@ -29,7 +30,7 @@ async function canUsePauseCodegen(repoDir) {
|
|
|
29
30
|
if (!isRunningHeaded) {
|
|
30
31
|
// This codegen approach requires running Playwright in headed mode because
|
|
31
32
|
// it depends on the page.pause() API, which is no-op in headless mode
|
|
32
|
-
|
|
33
|
+
logger_1.logger.error("Cannot use pause codegen because RUN_PLAYWRIGHT_HEADED is not true");
|
|
33
34
|
return false;
|
|
34
35
|
}
|
|
35
36
|
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
|
@@ -37,7 +38,7 @@ async function canUsePauseCodegen(repoDir) {
|
|
|
37
38
|
// PW_CODEGEN_NO_INSPECTOR should be set to true, so that Playwright runs the
|
|
38
39
|
// EmptyRecorderApp() -- which is the entrypoint to our patched code
|
|
39
40
|
// Ref: https://github.com/microsoft/playwright/blob/c96558d0691c0377dbc0c772a1bd8120d546e6d7/packages/playwright-core/src/server/recorder/recorderApp.ts#L98
|
|
40
|
-
|
|
41
|
+
logger_1.logger.error("Cannot use pause codegen because PW_CODEGEN_NO_INSPECTOR is not set");
|
|
41
42
|
return false;
|
|
42
43
|
}
|
|
43
44
|
// Need all conditions to be met to use pause codegen
|
|
@@ -3,7 +3,7 @@ declare class APIClient {
|
|
|
3
3
|
constructor();
|
|
4
4
|
request(endpoint: string, options?: RequestInit): Promise<Response>;
|
|
5
5
|
private makeRequest;
|
|
6
|
-
|
|
6
|
+
ensureAuthenticated(): Promise<void>;
|
|
7
7
|
private refreshToken;
|
|
8
8
|
}
|
|
9
9
|
export declare const apiClient: APIClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/auth/api-client.ts"],"names":[],"mappings":"AAQA,cAAM,SAAS;IACb,OAAO,CAAC,MAAM,CAAS;;IAMjB,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,QAAQ,CAAC;YA2BN,WAAW;
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/auth/api-client.ts"],"names":[],"mappings":"AAQA,cAAM,SAAS;IACb,OAAO,CAAC,MAAM,CAAS;;IAMjB,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,QAAQ,CAAC;YA2BN,WAAW;IAuBnB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;YAiB5B,YAAY;CA4C3B;AAED,eAAO,MAAM,SAAS,WAAkB,CAAC"}
|
package/dist/auth/cli-auth.js
CHANGED
|
@@ -147,7 +147,7 @@ async function authenticate() {
|
|
|
147
147
|
server.listen(clientPort, () => {
|
|
148
148
|
// Open browser to your Next.js auth page
|
|
149
149
|
const authUrl = `${appUrl}/auth/cli?redirect_uri=${encodeURIComponent(redirectUri)}`;
|
|
150
|
-
console.log("Opening browser for authentication
|
|
150
|
+
console.log("🔐 Opening browser for authentication...\n");
|
|
151
151
|
console.log(`If the browser doesn't open automatically, visit: ${authUrl}`);
|
|
152
152
|
(0, open_1.default)(authUrl).catch((err) => {
|
|
153
153
|
console.warn("Could not open browser automatically:", err.message);
|
package/dist/bin/index.js
CHANGED
|
@@ -199,7 +199,6 @@ async function main() {
|
|
|
199
199
|
.command("login")
|
|
200
200
|
.description("Authenticate with your Empirical account")
|
|
201
201
|
.action(async () => {
|
|
202
|
-
console.log("🔐 Starting authentication...\n");
|
|
203
202
|
try {
|
|
204
203
|
const result = await (0, auth_1.authenticate)();
|
|
205
204
|
if (result.success) {
|
|
@@ -207,7 +206,6 @@ async function main() {
|
|
|
207
206
|
if (result.user) {
|
|
208
207
|
console.log(`👤 Logged in as: ${result.user.email}`);
|
|
209
208
|
}
|
|
210
|
-
console.log("\nYou can now use authenticated CLI commands.\n");
|
|
211
209
|
}
|
|
212
210
|
else {
|
|
213
211
|
console.error("❌ Authentication failed:", result.error);
|
package/dist/bin/utils/index.js
CHANGED
|
@@ -100,7 +100,7 @@ async function printBanner() {
|
|
|
100
100
|
versionSuffix = ` (latest)`;
|
|
101
101
|
}
|
|
102
102
|
else {
|
|
103
|
-
versionSuffix = ` ${reset}(latest is ${latestVersion})`;
|
|
103
|
+
versionSuffix = ` ${reset}(latest is v${latestVersion})`;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
106
|
const logLine1 = `Running ${PACKAGE_NAME} v${version}${versionSuffix}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAKlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,UAAU,CAAC,CAAa;IAEhC,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,KAAK,CAAoB;IAEjC,OAAO,CAAC,cAAc,CAAqB;gBAE/B,EACV,IAAI,EACJ,OAAO,EACP,UAAU,EACV,UAAU,GACX,EAAE;QACD,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;KACzB;IAOD,iBAAiB;;;;IAIjB,2BAA2B;IAI3B,iBAAiB;IAIjB,WAAW,CAAC,QAAQ,EAAE,MAAM;IAItB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAKlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,UAAU,CAAC,CAAa;IAEhC,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,KAAK,CAAoB;IAEjC,OAAO,CAAC,cAAc,CAAqB;gBAE/B,EACV,IAAI,EACJ,OAAO,EACP,UAAU,EACV,UAAU,GACX,EAAE;QACD,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;KACzB;IAOD,iBAAiB;;;;IAIjB,2BAA2B;IAI3B,iBAAiB;IAIjB,WAAW,CAAC,QAAQ,EAAE,MAAM;IAItB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IA8HnC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB5B"}
|
package/dist/file/server.js
CHANGED
|
@@ -42,6 +42,62 @@ class FileServiceServer {
|
|
|
42
42
|
const app = (0, express_1.default)();
|
|
43
43
|
app.use(express_1.default.json({ limit: "50mb" }));
|
|
44
44
|
(0, ipc_1.humanLoopRoute)(app);
|
|
45
|
+
app.get("/ready", (req, res) => {
|
|
46
|
+
const html = `
|
|
47
|
+
<!DOCTYPE html>
|
|
48
|
+
<html>
|
|
49
|
+
<head>
|
|
50
|
+
<title>Record</title>
|
|
51
|
+
<style>
|
|
52
|
+
body {
|
|
53
|
+
display: flex;
|
|
54
|
+
justify-content: center;
|
|
55
|
+
align-items: center;
|
|
56
|
+
height: 100vh;
|
|
57
|
+
margin: 0;
|
|
58
|
+
font-family: sans-serif;
|
|
59
|
+
font-size: 24px;
|
|
60
|
+
}
|
|
61
|
+
.message {
|
|
62
|
+
opacity: 0;
|
|
63
|
+
animation: fadeIn 0.5s ease-in forwards;
|
|
64
|
+
}
|
|
65
|
+
.pulsate {
|
|
66
|
+
animation: pulsate 1s ease-in-out infinite;
|
|
67
|
+
}
|
|
68
|
+
@keyframes fadeIn {
|
|
69
|
+
to {
|
|
70
|
+
opacity: 1;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
@keyframes pulsate {
|
|
74
|
+
0%, 100% {
|
|
75
|
+
opacity: 1;
|
|
76
|
+
}
|
|
77
|
+
50% {
|
|
78
|
+
opacity: 0.6;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
</style>
|
|
82
|
+
</head>
|
|
83
|
+
<body>
|
|
84
|
+
<div class="message pulsate" id="message">Getting ready to record</div>
|
|
85
|
+
<script>
|
|
86
|
+
setTimeout(() => {
|
|
87
|
+
const message = document.getElementById('message');
|
|
88
|
+
message.className = 'message';
|
|
89
|
+
message.style.opacity = '0';
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
message.textContent = 'Ready to record';
|
|
92
|
+
message.style.opacity = '1';
|
|
93
|
+
}, 300);
|
|
94
|
+
}, 2000);
|
|
95
|
+
</script>
|
|
96
|
+
</body>
|
|
97
|
+
</html>
|
|
98
|
+
`;
|
|
99
|
+
res.send(html);
|
|
100
|
+
});
|
|
45
101
|
app.post("/codegen-sources", async (req) => {
|
|
46
102
|
const payload = req.body;
|
|
47
103
|
this.codegenSources = payload.map((c) => c.actions.join("\n")).join("\n");
|
package/dist/index.js
CHANGED
|
@@ -103,7 +103,7 @@ async function recordTest(pageRef) {
|
|
|
103
103
|
const repoDir = process.cwd();
|
|
104
104
|
const canUsePwPause = await (0, pw_pause_1.canUsePauseCodegen)(repoDir);
|
|
105
105
|
if (!canUsePwPause) {
|
|
106
|
-
|
|
106
|
+
throw new Error("Unable to start recording: please report this issue.");
|
|
107
107
|
}
|
|
108
108
|
logger_1.logger.debug("[getCodegen] using PlaywrightPauseCodegen");
|
|
109
109
|
const codegen = new for_recorder_1.PlaywrightPauseCodegenForRecorder(async (sources) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recorder/index.ts"],"names":[],"mappings":"AAkBA,wBAAsB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recorder/index.ts"],"names":[],"mappings":"AAkBA,wBAAsB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,iBAgG3D"}
|
package/dist/recorder/index.js
CHANGED
|
@@ -9,9 +9,9 @@ const detect_port_1 = __importDefault(require("detect-port"));
|
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const utils_1 = require("../agent/browsing/utils");
|
|
11
11
|
const pw_pause_1 = require("../agent/cua/pw-codegen/pw-pause");
|
|
12
|
+
const api_client_1 = require("../auth/api-client");
|
|
12
13
|
const server_1 = require("../file/server");
|
|
13
14
|
const logger_1 = require("../logger");
|
|
14
|
-
const display_1 = require("./display");
|
|
15
15
|
const env_variables_1 = require("./env-variables");
|
|
16
16
|
const request_1 = require("./request");
|
|
17
17
|
const temp_files_1 = require("./temp-files");
|
|
@@ -19,6 +19,13 @@ const upload_1 = require("./upload");
|
|
|
19
19
|
const validation_1 = require("./validation");
|
|
20
20
|
async function runRecorder({ name }) {
|
|
21
21
|
console.log(`Recording for test name: ${name}`);
|
|
22
|
+
try {
|
|
23
|
+
await api_client_1.apiClient.ensureAuthenticated();
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.error("Authentication required: please run @empiricalrun/test-gen login first");
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
22
29
|
const repoDir = process.cwd();
|
|
23
30
|
let repoName = "";
|
|
24
31
|
let fileServer = null;
|
|
@@ -50,9 +57,6 @@ async function runRecorder({ name }) {
|
|
|
50
57
|
logger_1.logger.warn("[generateTestWithBrowserAgent] Error preparing playwright for codegen", err);
|
|
51
58
|
}
|
|
52
59
|
const envVariables = await (0, env_variables_1.fetchEnvironmentVariables)(repoName);
|
|
53
|
-
await (0, temp_files_1.createTempTestFile)();
|
|
54
|
-
const absFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
|
|
55
|
-
await (0, utils_1.addImportForMethod)(absFilePath, "recordTest");
|
|
56
60
|
// Start a file service for IPC with the agent (which runs in a different process)
|
|
57
61
|
const availablePort = await (0, detect_port_1.default)(3030);
|
|
58
62
|
fileServer = new server_1.FileServiceServer({
|
|
@@ -61,6 +65,9 @@ async function runRecorder({ name }) {
|
|
|
61
65
|
updateFile: false,
|
|
62
66
|
});
|
|
63
67
|
await fileServer.startFileService();
|
|
68
|
+
await (0, temp_files_1.createTempTestFile)(availablePort);
|
|
69
|
+
const absFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
|
|
70
|
+
await (0, utils_1.addImportForMethod)(absFilePath, "recordTest");
|
|
64
71
|
await (0, test_run_1.runSingleTest)({
|
|
65
72
|
testName: "temp test",
|
|
66
73
|
suites: [],
|
|
@@ -89,11 +96,10 @@ async function runRecorder({ name }) {
|
|
|
89
96
|
await (0, pw_pause_1.revertToOriginalPwCode)(repoDir);
|
|
90
97
|
const codegenResult = fileServer.getCodegenSources();
|
|
91
98
|
await fileServer.stop();
|
|
92
|
-
const finalCode = await (0, display_1.displayResultsAndConfirm)(name, codegenResult);
|
|
93
99
|
await (0, request_1.sendToDashboardAsRequest)({
|
|
94
100
|
repoName,
|
|
95
101
|
testName: name,
|
|
96
|
-
codegenResult:
|
|
102
|
+
codegenResult: codegenResult,
|
|
97
103
|
attachments,
|
|
98
104
|
});
|
|
99
105
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/recorder/request.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/recorder/request.ts"],"names":[],"mappings":"AA+KA,wBAAsB,wBAAwB,CAAC,EAC7C,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,WAAW,GACZ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,iBAmBA"}
|
package/dist/recorder/request.js
CHANGED
|
@@ -1,21 +1,172 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.sendToDashboardAsRequest = sendToDashboardAsRequest;
|
|
7
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
4
8
|
const api_client_1 = require("../auth/api-client");
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
function truncateForDisplay(text, maxLineLength) {
|
|
10
|
+
const lines = text.split("\n");
|
|
11
|
+
return lines
|
|
12
|
+
.map((line) => {
|
|
13
|
+
if (line.length <= maxLineLength) {
|
|
14
|
+
return line;
|
|
15
|
+
}
|
|
16
|
+
return line.substring(0, maxLineLength - 3) + "...";
|
|
17
|
+
})
|
|
18
|
+
.join("\n");
|
|
19
|
+
}
|
|
20
|
+
function wrapText(text, width) {
|
|
21
|
+
const allLines = [];
|
|
22
|
+
// Split by newlines first to preserve existing line breaks
|
|
23
|
+
const paragraphs = text.split("\n");
|
|
24
|
+
for (const paragraph of paragraphs) {
|
|
25
|
+
if (paragraph.trim() === "") {
|
|
26
|
+
allLines.push("");
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
// If the line is already shorter than width, use it as-is
|
|
30
|
+
if (paragraph.length <= width) {
|
|
31
|
+
allLines.push(paragraph);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
// Otherwise, wrap the line
|
|
35
|
+
const words = paragraph.split(" ");
|
|
36
|
+
let currentLine = "";
|
|
37
|
+
for (const word of words) {
|
|
38
|
+
if (currentLine.length + word.length + 1 <= width) {
|
|
39
|
+
currentLine += (currentLine.length > 0 ? " " : "") + word;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
if (currentLine.length > 0) {
|
|
43
|
+
allLines.push(currentLine);
|
|
44
|
+
currentLine = word;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// Word is longer than width, split it into chunks
|
|
48
|
+
if (word.length > width) {
|
|
49
|
+
let remainingWord = word;
|
|
50
|
+
while (remainingWord.length > width) {
|
|
51
|
+
allLines.push(remainingWord.substring(0, width));
|
|
52
|
+
remainingWord = remainingWord.substring(width);
|
|
53
|
+
}
|
|
54
|
+
currentLine = remainingWord;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
currentLine = word;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (currentLine.length > 0) {
|
|
63
|
+
allLines.push(currentLine);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return allLines;
|
|
67
|
+
}
|
|
68
|
+
function printInBox(header, title, description) {
|
|
69
|
+
const boxWidth = 80;
|
|
70
|
+
const contentWidth = boxWidth - 4; // Account for borders and padding
|
|
71
|
+
// Create box with padding
|
|
72
|
+
console.log("\n" + "┌" + "─".repeat(boxWidth - 2) + "┐");
|
|
73
|
+
// Header section
|
|
74
|
+
console.log("│ " + header + " ".repeat(boxWidth - 4 - header.length) + "│");
|
|
75
|
+
console.log("│" + "─".repeat(boxWidth - 2) + "│");
|
|
76
|
+
// Title content with wrapping
|
|
77
|
+
const titleLines = wrapText(title, contentWidth - 2);
|
|
78
|
+
titleLines.forEach((line) => {
|
|
79
|
+
const padding = Math.max(0, boxWidth - 4 - line.length);
|
|
80
|
+
console.log("│ " + line + " ".repeat(padding) + "│");
|
|
81
|
+
});
|
|
82
|
+
console.log("│" + "─".repeat(boxWidth - 2) + "│");
|
|
83
|
+
console.log("│ Description:" + " ".repeat(boxWidth - 16) + "│");
|
|
84
|
+
console.log("│" + " ".repeat(boxWidth - 2) + "│");
|
|
85
|
+
// Description content with wrapping
|
|
86
|
+
const descriptionLines = wrapText(description, contentWidth - 2);
|
|
87
|
+
descriptionLines.forEach((line) => {
|
|
88
|
+
const padding = Math.max(0, boxWidth - 4 - line.length);
|
|
89
|
+
console.log("│ " + line + " ".repeat(padding) + "│");
|
|
90
|
+
});
|
|
91
|
+
console.log("│" + " ".repeat(boxWidth - 2) + "│");
|
|
92
|
+
console.log("└" + "─".repeat(boxWidth - 2) + "┘");
|
|
93
|
+
}
|
|
94
|
+
const defaultTitle = (name) => `Add a test: ${name}`;
|
|
95
|
+
function defaultDescription(codegenResult, attachments) {
|
|
96
|
+
const backtickedCodegenResult = `\`\`\`\n${codegenResult}\n\`\`\``;
|
|
7
97
|
return [
|
|
8
98
|
`To add this test, refer to the following code and videos that were captured using playwright codegen. Make modifications that you need to make to convert this into a test case that sits well with other tests in this repository.`,
|
|
9
99
|
`Codegen result:`,
|
|
10
|
-
|
|
100
|
+
backtickedCodegenResult,
|
|
11
101
|
...attachments.map((attachment) => `[[${attachment}]]`),
|
|
12
102
|
].join("\n\n");
|
|
13
103
|
}
|
|
104
|
+
function defaultDescriptionForDisplay(codegenResult, attachments) {
|
|
105
|
+
const truncatedCodegenResult = truncateForDisplay(codegenResult, 74);
|
|
106
|
+
const backtickedCodegenResult = `\`\`\`\n${truncatedCodegenResult}\n\`\`\``;
|
|
107
|
+
return [
|
|
108
|
+
`To add this test, refer to the following code and videos that were captured using playwright codegen. Make modifications that you need to make to convert this into a test case that sits well with other tests in this repository.`,
|
|
109
|
+
`Codegen result:`,
|
|
110
|
+
backtickedCodegenResult,
|
|
111
|
+
...attachments.map((attachment) => `[[${attachment}]]`),
|
|
112
|
+
].join("\n\n");
|
|
113
|
+
}
|
|
114
|
+
async function confirmRequestDetails(initialTitle, initialDescription, initialDescriptionForDisplay) {
|
|
115
|
+
let finalTitle = initialTitle;
|
|
116
|
+
let finalDescription = initialDescription;
|
|
117
|
+
let finalDescriptionForDisplay = initialDescriptionForDisplay;
|
|
118
|
+
let approved = false;
|
|
119
|
+
while (!approved) {
|
|
120
|
+
printInBox("📝 Create new request", finalTitle, finalDescriptionForDisplay);
|
|
121
|
+
const { confirmed } = await inquirer_1.default.prompt([
|
|
122
|
+
{
|
|
123
|
+
type: "confirm",
|
|
124
|
+
name: "confirmed",
|
|
125
|
+
message: "Does this look good to send to the dashboard?",
|
|
126
|
+
default: true,
|
|
127
|
+
},
|
|
128
|
+
]);
|
|
129
|
+
if (confirmed) {
|
|
130
|
+
console.log("✅ Great! Sending request to dashboard...");
|
|
131
|
+
approved = true;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// Let user edit title and description
|
|
135
|
+
const { editedTitle } = await inquirer_1.default.prompt([
|
|
136
|
+
{
|
|
137
|
+
type: "input",
|
|
138
|
+
name: "editedTitle",
|
|
139
|
+
message: "Edit the title:",
|
|
140
|
+
default: finalTitle,
|
|
141
|
+
},
|
|
142
|
+
]);
|
|
143
|
+
const { editedDescription } = await inquirer_1.default.prompt([
|
|
144
|
+
{
|
|
145
|
+
type: "editor",
|
|
146
|
+
name: "editedDescription",
|
|
147
|
+
message: "Edit the description:",
|
|
148
|
+
default: finalDescription,
|
|
149
|
+
},
|
|
150
|
+
]);
|
|
151
|
+
finalTitle = editedTitle;
|
|
152
|
+
finalDescription = editedDescription;
|
|
153
|
+
// For simplicity, if description is edited, just use it as-is for display
|
|
154
|
+
finalDescriptionForDisplay = editedDescription;
|
|
155
|
+
console.clear();
|
|
156
|
+
console.log("Request details updated.");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return { title: finalTitle, description: finalDescription };
|
|
160
|
+
}
|
|
14
161
|
async function sendToDashboardAsRequest({ repoName, testName, codegenResult, attachments, }) {
|
|
162
|
+
const initialTitle = defaultTitle(testName);
|
|
163
|
+
const initialDescription = defaultDescription(codegenResult, attachments);
|
|
164
|
+
const initialDescriptionForDisplay = defaultDescriptionForDisplay(codegenResult, attachments);
|
|
165
|
+
const { title, description } = await confirmRequestDetails(initialTitle, initialDescription, initialDescriptionForDisplay);
|
|
15
166
|
return createRequest({
|
|
16
167
|
repoName,
|
|
17
|
-
title
|
|
18
|
-
description
|
|
168
|
+
title,
|
|
169
|
+
description,
|
|
19
170
|
});
|
|
20
171
|
}
|
|
21
172
|
async function createRequest({ repoName, title, description, }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"temp-files.d.ts","sourceRoot":"","sources":["../../src/recorder/temp-files.ts"],"names":[],"mappings":"AAKA,wBAAsB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"temp-files.d.ts","sourceRoot":"","sources":["../../src/recorder/temp-files.ts"],"names":[],"mappings":"AAKA,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,iBAmBpD;AAED,wBAAsB,kBAAkB,kBAUvC"}
|
|
@@ -8,7 +8,7 @@ exports.deleteTempTestFile = deleteTempTestFile;
|
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const logger_1 = require("../logger");
|
|
11
|
-
async function createTempTestFile() {
|
|
11
|
+
async function createTempTestFile(port) {
|
|
12
12
|
const tempFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
|
|
13
13
|
// Check if the temp file already exists
|
|
14
14
|
if (fs_1.default.existsSync(tempFilePath)) {
|
|
@@ -19,8 +19,7 @@ async function createTempTestFile() {
|
|
|
19
19
|
const content = `import { test, expect } from './fixtures';
|
|
20
20
|
|
|
21
21
|
test('temp test', async ({ page }) => {
|
|
22
|
-
await page.goto('
|
|
23
|
-
expect(await page.title()).toBe('Example Domain');
|
|
22
|
+
await page.goto('http://localhost:${port}/ready');
|
|
24
23
|
await recordTest(page);
|
|
25
24
|
});
|
|
26
25
|
`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empiricalrun/test-gen",
|
|
3
|
-
"version": "0.69.
|
|
3
|
+
"version": "0.69.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"zod": "^3.23.8",
|
|
67
67
|
"@empiricalrun/llm": "^0.19.0",
|
|
68
68
|
"@empiricalrun/r2-uploader": "^0.3.9",
|
|
69
|
-
"@empiricalrun/test-run": "^0.10.
|
|
69
|
+
"@empiricalrun/test-run": "^0.10.5"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@playwright/test": "1.53.0",
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/index.ts","./src/logger.ts","./src/actions/assert.ts","./src/actions/click.ts","./src/actions/done.ts","./src/actions/fill.ts","./src/actions/goto.ts","./src/actions/hover.ts","./src/actions/index.ts","./src/actions/next-task.ts","./src/actions/press.ts","./src/actions/skill.ts","./src/actions/text-content.ts","./src/actions/constants/index.ts","./src/actions/utils/index.ts","./src/agent/browsing/index.ts","./src/agent/browsing/run.ts","./src/agent/browsing/utils.ts","./src/agent/chat/agent-loop.ts","./src/agent/chat/exports.ts","./src/agent/chat/index.ts","./src/agent/chat/models.ts","./src/agent/chat/state.ts","./src/agent/chat/types.ts","./src/agent/chat/utils.ts","./src/agent/chat/prompt/index.ts","./src/agent/chat/prompt/pw-utils-docs.ts","./src/agent/chat/prompt/repo.ts","./src/agent/codegen/create-test-block.ts","./src/agent/codegen/fix-ts-errors.ts","./src/agent/codegen/generate-code-apply-changes.ts","./src/agent/codegen/lexical-scoped-vars.ts","./src/agent/codegen/repo-edit.ts","./src/agent/codegen/run.ts","./src/agent/codegen/skills-retriever.ts","./src/agent/codegen/test-update-feedback.ts","./src/agent/codegen/types.ts","./src/agent/codegen/update-flow.ts","./src/agent/codegen/use-skill.ts","./src/agent/codegen/utils.ts","./src/agent/cua/computer.ts","./src/agent/cua/index.ts","./src/agent/cua/model.ts","./src/agent/cua/pw-codegen/element-from-point.ts","./src/agent/cua/pw-codegen/types.ts","./src/agent/cua/pw-codegen/pw-pause/for-recorder.ts","./src/agent/cua/pw-codegen/pw-pause/index.ts","./src/agent/cua/pw-codegen/pw-pause/ipc.ts","./src/agent/cua/pw-codegen/pw-pause/patch.ts","./src/agent/cua/pw-codegen/pw-pause/types.ts","./src/agent/diagnosis-agent/index.ts","./src/agent/diagnosis-agent/strict-mode-violation.ts","./src/agent/enrich-prompt/index.ts","./src/agent/enrich-prompt/utils.ts","./src/agent/infer-agent/index.ts","./src/agent/master/action-tool-calls.ts","./src/agent/master/element-annotation.ts","./src/agent/master/execute-browser-action.ts","./src/agent/master/execute-skill-action.ts","./src/agent/master/next-action.ts","./src/agent/master/planner.ts","./src/agent/master/run.ts","./src/agent/master/scroller.ts","./src/agent/master/with-hints.ts","./src/agent/master/browser-tests/cua.spec.ts","./src/agent/master/browser-tests/fixtures.ts","./src/agent/master/browser-tests/index.spec.ts","./src/agent/master/browser-tests/skills.spec.ts","./src/agent/master/icon-descriptor/index.ts","./src/agent/master/icon-descriptor/normalize-svg.ts","./src/agent/planner/run-time-planner.ts","./src/agent/planner/run.ts","./src/artifacts/index.ts","./src/artifacts/utils.ts","./src/auth/api-client.ts","./src/auth/cli-auth.ts","./src/auth/index.ts","./src/auth/token-store.ts","./src/bin/index.ts","./src/bin/setup.ts","./src/bin/logger/index.ts","./src/bin/utils/context.ts","./src/bin/utils/index.ts","./src/bin/utils/fs/index.ts","./src/bin/utils/platform/web/index.ts","./src/bin/utils/platform/web/test-files/ts-path-import-validate.ts","./src/bin/utils/scenarios/index.ts","./src/browser-injected-scripts/annotate-elements.spec.ts","./src/constants/index.ts","./src/errors/index.ts","./src/evals/add-scenario-agent.evals.ts","./src/evals/append-create-test-agent.evals.ts","./src/evals/fetch-pom-skills-agent.evals.ts","./src/evals/infer-master-or-code-agent.evals.ts","./src/evals/master-agent.evals.ts","./src/evals/type.ts","./src/evals/update-scenario-agent.evals.ts","./src/file/client.ts","./src/file/server.ts","./src/human-in-the-loop/cli.ts","./src/human-in-the-loop/index.ts","./src/human-in-the-loop/ipc.ts","./src/page/index.ts","./src/prompts/lib/ts-transformer.ts","./src/recorder/
|
|
1
|
+
{"root":["./src/index.ts","./src/logger.ts","./src/actions/assert.ts","./src/actions/click.ts","./src/actions/done.ts","./src/actions/fill.ts","./src/actions/goto.ts","./src/actions/hover.ts","./src/actions/index.ts","./src/actions/next-task.ts","./src/actions/press.ts","./src/actions/skill.ts","./src/actions/text-content.ts","./src/actions/constants/index.ts","./src/actions/utils/index.ts","./src/agent/browsing/index.ts","./src/agent/browsing/run.ts","./src/agent/browsing/utils.ts","./src/agent/chat/agent-loop.ts","./src/agent/chat/exports.ts","./src/agent/chat/index.ts","./src/agent/chat/models.ts","./src/agent/chat/state.ts","./src/agent/chat/types.ts","./src/agent/chat/utils.ts","./src/agent/chat/prompt/index.ts","./src/agent/chat/prompt/pw-utils-docs.ts","./src/agent/chat/prompt/repo.ts","./src/agent/codegen/create-test-block.ts","./src/agent/codegen/fix-ts-errors.ts","./src/agent/codegen/generate-code-apply-changes.ts","./src/agent/codegen/lexical-scoped-vars.ts","./src/agent/codegen/repo-edit.ts","./src/agent/codegen/run.ts","./src/agent/codegen/skills-retriever.ts","./src/agent/codegen/test-update-feedback.ts","./src/agent/codegen/types.ts","./src/agent/codegen/update-flow.ts","./src/agent/codegen/use-skill.ts","./src/agent/codegen/utils.ts","./src/agent/cua/computer.ts","./src/agent/cua/index.ts","./src/agent/cua/model.ts","./src/agent/cua/pw-codegen/element-from-point.ts","./src/agent/cua/pw-codegen/types.ts","./src/agent/cua/pw-codegen/pw-pause/for-recorder.ts","./src/agent/cua/pw-codegen/pw-pause/index.ts","./src/agent/cua/pw-codegen/pw-pause/ipc.ts","./src/agent/cua/pw-codegen/pw-pause/patch.ts","./src/agent/cua/pw-codegen/pw-pause/types.ts","./src/agent/diagnosis-agent/index.ts","./src/agent/diagnosis-agent/strict-mode-violation.ts","./src/agent/enrich-prompt/index.ts","./src/agent/enrich-prompt/utils.ts","./src/agent/infer-agent/index.ts","./src/agent/master/action-tool-calls.ts","./src/agent/master/element-annotation.ts","./src/agent/master/execute-browser-action.ts","./src/agent/master/execute-skill-action.ts","./src/agent/master/next-action.ts","./src/agent/master/planner.ts","./src/agent/master/run.ts","./src/agent/master/scroller.ts","./src/agent/master/with-hints.ts","./src/agent/master/browser-tests/cua.spec.ts","./src/agent/master/browser-tests/fixtures.ts","./src/agent/master/browser-tests/index.spec.ts","./src/agent/master/browser-tests/skills.spec.ts","./src/agent/master/icon-descriptor/index.ts","./src/agent/master/icon-descriptor/normalize-svg.ts","./src/agent/planner/run-time-planner.ts","./src/agent/planner/run.ts","./src/artifacts/index.ts","./src/artifacts/utils.ts","./src/auth/api-client.ts","./src/auth/cli-auth.ts","./src/auth/index.ts","./src/auth/token-store.ts","./src/bin/index.ts","./src/bin/setup.ts","./src/bin/logger/index.ts","./src/bin/utils/context.ts","./src/bin/utils/index.ts","./src/bin/utils/fs/index.ts","./src/bin/utils/platform/web/index.ts","./src/bin/utils/platform/web/test-files/ts-path-import-validate.ts","./src/bin/utils/scenarios/index.ts","./src/browser-injected-scripts/annotate-elements.spec.ts","./src/constants/index.ts","./src/errors/index.ts","./src/evals/add-scenario-agent.evals.ts","./src/evals/append-create-test-agent.evals.ts","./src/evals/fetch-pom-skills-agent.evals.ts","./src/evals/infer-master-or-code-agent.evals.ts","./src/evals/master-agent.evals.ts","./src/evals/type.ts","./src/evals/update-scenario-agent.evals.ts","./src/file/client.ts","./src/file/server.ts","./src/human-in-the-loop/cli.ts","./src/human-in-the-loop/index.ts","./src/human-in-the-loop/ipc.ts","./src/page/index.ts","./src/prompts/lib/ts-transformer.ts","./src/recorder/env-variables.ts","./src/recorder/index.ts","./src/recorder/request.ts","./src/recorder/temp-files.ts","./src/recorder/upload.ts","./src/recorder/validation.ts","./src/reporter/index.ts","./src/reporter/lib.ts","./src/session/index.ts","./src/test-build/index.ts","./src/tool-call-service/index.ts","./src/tool-call-service/utils.ts","./src/tools/commit-and-create-pr.ts","./src/tools/diagnosis-fetcher.ts","./src/tools/download-build.ts","./src/tools/list-environments.ts","./src/tools/str_replace_editor.ts","./src/tools/test-gen-browser.ts","./src/tools/test-run.ts","./src/tools/grep/index.ts","./src/tools/grep/ripgrep/index.ts","./src/tools/grep/ripgrep/types.ts","./src/tools/test-run-fetcher/index.ts","./src/tools/test-run-fetcher/types.ts","./src/tools/upgrade-packages/index.ts","./src/tools/upgrade-packages/utils.ts","./src/tools/utils/index.ts","./src/types/handlebars.d.ts","./src/types/index.ts","./src/uploader/index.ts","./src/uploader/utils.ts","./src/utils/checkpoint.ts","./src/utils/env.ts","./src/utils/exec.ts","./src/utils/file-tree.ts","./src/utils/file.ts","./src/utils/git.ts","./src/utils/html.ts","./src/utils/index.ts","./src/utils/json.ts","./src/utils/repo-tree.ts","./src/utils/slug.ts","./src/utils/string.ts","./src/utils/stripAnsi.ts"],"version":"5.8.3"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/recorder/display.ts"],"names":[],"mappings":"AAEA,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,mBA+CtB"}
|
package/dist/recorder/display.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.displayResultsAndConfirm = displayResultsAndConfirm;
|
|
7
|
-
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
|
-
async function displayResultsAndConfirm(name, codegenResult) {
|
|
9
|
-
let finalResult = codegenResult || "No code generated";
|
|
10
|
-
let approved = false;
|
|
11
|
-
while (!approved) {
|
|
12
|
-
// Display results in a box format
|
|
13
|
-
console.log("\n" + "=".repeat(80));
|
|
14
|
-
console.log("📝 TEST GENERATION RESULTS");
|
|
15
|
-
console.log("=".repeat(80));
|
|
16
|
-
console.log(`Test Name: ${name}`);
|
|
17
|
-
console.log("-".repeat(80));
|
|
18
|
-
console.log("Generated Code:");
|
|
19
|
-
console.log("-".repeat(80));
|
|
20
|
-
console.log(finalResult);
|
|
21
|
-
console.log("=".repeat(80));
|
|
22
|
-
// Ask user for confirmation
|
|
23
|
-
const { confirmed } = await inquirer_1.default.prompt([
|
|
24
|
-
{
|
|
25
|
-
type: "confirm",
|
|
26
|
-
name: "confirmed",
|
|
27
|
-
message: "Does this look good to you?",
|
|
28
|
-
default: true,
|
|
29
|
-
},
|
|
30
|
-
]);
|
|
31
|
-
if (confirmed) {
|
|
32
|
-
console.log("✅ Great! The test generation was successful.");
|
|
33
|
-
approved = true;
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
// Open multiline editor for user to modify
|
|
37
|
-
const { editedCode } = await inquirer_1.default.prompt([
|
|
38
|
-
{
|
|
39
|
-
type: "editor",
|
|
40
|
-
name: "editedCode",
|
|
41
|
-
message: "Edit the generated code:",
|
|
42
|
-
default: finalResult,
|
|
43
|
-
},
|
|
44
|
-
]);
|
|
45
|
-
finalResult = editedCode;
|
|
46
|
-
console.log("Code updated. Let's review the changes...");
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return finalResult;
|
|
50
|
-
}
|