@empiricalrun/test-gen 0.68.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 +25 -0
- package/dist/agent/chat/exports.d.ts +8 -8
- package/dist/agent/chat/exports.d.ts.map +1 -1
- package/dist/agent/chat/exports.js +10 -7
- package/dist/agent/chat/index.d.ts.map +1 -1
- package/dist/agent/chat/index.js +5 -2
- package/dist/agent/chat/state.d.ts +4 -2
- package/dist/agent/chat/state.d.ts.map +1 -1
- package/dist/agent/chat/state.js +10 -2
- package/dist/agent/chat/utils.d.ts +5 -1
- package/dist/agent/chat/utils.d.ts.map +1 -1
- package/dist/agent/chat/utils.js +22 -0
- package/dist/agent/cua/pw-codegen/pw-pause/for-recorder.d.ts.map +1 -1
- package/dist/agent/cua/pw-codegen/pw-pause/for-recorder.js +24 -3
- 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/agent/cua/pw-codegen/pw-pause/patch.d.ts.map +1 -1
- package/dist/agent/cua/pw-codegen/pw-pause/patch.js +4 -6
- package/dist/auth/api-client.d.ts +1 -1
- package/dist/auth/api-client.d.ts.map +1 -1
- package/dist/auth/api-client.js +3 -2
- package/dist/auth/cli-auth.js +1 -1
- package/dist/bin/index.js +10 -2
- package/dist/bin/setup.d.ts +4 -0
- package/dist/bin/setup.d.ts.map +1 -0
- package/dist/bin/setup.js +86 -0
- package/dist/bin/utils/index.d.ts +1 -0
- package/dist/bin/utils/index.d.ts.map +1 -1
- package/dist/bin/utils/index.js +1 -1
- package/dist/file/server.d.ts.map +1 -1
- package/dist/file/server.js +60 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/logger.d.ts +3 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +11 -0
- package/dist/recorder/index.d.ts.map +1 -1
- package/dist/recorder/index.js +31 -11
- package/dist/recorder/request.d.ts.map +1 -1
- package/dist/recorder/request.js +158 -8
- 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 +7 -7
- package/dist/recorder/upload.d.ts.map +1 -1
- package/dist/recorder/upload.js +0 -1
- package/package.json +6 -4
- 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/dist/file/server.js
CHANGED
|
@@ -42,10 +42,69 @@ 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");
|
|
48
|
-
console.log(
|
|
104
|
+
// console.log(
|
|
105
|
+
// "[FileServiceServer] Received codegen sources",
|
|
106
|
+
// this.codegenSources,
|
|
107
|
+
// );
|
|
49
108
|
});
|
|
50
109
|
app.post("/agent-results", async (req, res) => {
|
|
51
110
|
const { generatedCode, importPaths, result, usage } = req.body;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAchD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAsB7C,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,IAAI,GAAG,YAAY,EAC5B,KAAK,CAAC,EAAE,SAAS,iBAwElB;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,IAAI,iBAY7C"}
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const for_recorder_1 = require("./agent/cua/pw-codegen/pw-pause/for-recorder");
|
|
|
13
13
|
const run_1 = require("./agent/master/run");
|
|
14
14
|
const scenarios_1 = require("./bin/utils/scenarios");
|
|
15
15
|
const client_1 = __importDefault(require("./file/client"));
|
|
16
|
+
const logger_1 = require("./logger");
|
|
16
17
|
const reporter_1 = require("./reporter");
|
|
17
18
|
const session_1 = require("./session");
|
|
18
19
|
var test_build_1 = require("./test-build");
|
|
@@ -102,9 +103,9 @@ async function recordTest(pageRef) {
|
|
|
102
103
|
const repoDir = process.cwd();
|
|
103
104
|
const canUsePwPause = await (0, pw_pause_1.canUsePauseCodegen)(repoDir);
|
|
104
105
|
if (!canUsePwPause) {
|
|
105
|
-
|
|
106
|
+
throw new Error("Unable to start recording: please report this issue.");
|
|
106
107
|
}
|
|
107
|
-
|
|
108
|
+
logger_1.logger.debug("[getCodegen] using PlaywrightPauseCodegen");
|
|
108
109
|
const codegen = new for_recorder_1.PlaywrightPauseCodegenForRecorder(async (sources) => {
|
|
109
110
|
await fileServiceClient.sendCodegenSources(sources);
|
|
110
111
|
});
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,MAAyB,MAAM,mBAAmB,CAAC;AAE1D,eAAO,MAAM,MAAM,eAGjB,CAAC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
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.logger = void 0;
|
|
7
|
+
const console_log_level_1 = __importDefault(require("console-log-level"));
|
|
8
|
+
exports.logger = (0, console_log_level_1.default)({
|
|
9
|
+
prefix: "test-gen",
|
|
10
|
+
level: process.env.LOG_LEVEL || "info",
|
|
11
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recorder/index.ts"],"names":[],"mappings":"
|
|
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,8 +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
|
-
const
|
|
14
|
+
const logger_1 = require("../logger");
|
|
14
15
|
const env_variables_1 = require("./env-variables");
|
|
15
16
|
const request_1 = require("./request");
|
|
16
17
|
const temp_files_1 = require("./temp-files");
|
|
@@ -18,8 +19,29 @@ const upload_1 = require("./upload");
|
|
|
18
19
|
const validation_1 = require("./validation");
|
|
19
20
|
async function runRecorder({ name }) {
|
|
20
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
|
+
}
|
|
21
29
|
const repoDir = process.cwd();
|
|
22
30
|
let repoName = "";
|
|
31
|
+
let fileServer = null;
|
|
32
|
+
process.on("SIGINT", async () => {
|
|
33
|
+
try {
|
|
34
|
+
await (0, temp_files_1.deleteTempTestFile)();
|
|
35
|
+
await (0, pw_pause_1.revertToOriginalPwCode)(repoDir);
|
|
36
|
+
if (fileServer) {
|
|
37
|
+
await fileServer.stop();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error("Error during cleanup:", error);
|
|
42
|
+
}
|
|
43
|
+
process.exit(0);
|
|
44
|
+
});
|
|
23
45
|
try {
|
|
24
46
|
repoName = await (0, validation_1.validatePackageJson)(repoDir);
|
|
25
47
|
}
|
|
@@ -28,25 +50,24 @@ async function runRecorder({ name }) {
|
|
|
28
50
|
process.exit(1);
|
|
29
51
|
}
|
|
30
52
|
try {
|
|
31
|
-
|
|
32
|
-
console.log("[generateTestWithBrowserAgent] Preparing playwright for codegen");
|
|
53
|
+
logger_1.logger.debug("[generateTestWithBrowserAgent] Preparing playwright for codegen");
|
|
33
54
|
await (0, pw_pause_1.preparePlaywrightForCodegen)(repoDir);
|
|
34
55
|
}
|
|
35
56
|
catch (err) {
|
|
36
|
-
|
|
57
|
+
logger_1.logger.warn("[generateTestWithBrowserAgent] Error preparing playwright for codegen", err);
|
|
37
58
|
}
|
|
38
59
|
const envVariables = await (0, env_variables_1.fetchEnvironmentVariables)(repoName);
|
|
39
|
-
await (0, temp_files_1.createTempTestFile)();
|
|
40
|
-
const absFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
|
|
41
|
-
await (0, utils_1.addImportForMethod)(absFilePath, "recordTest");
|
|
42
60
|
// Start a file service for IPC with the agent (which runs in a different process)
|
|
43
61
|
const availablePort = await (0, detect_port_1.default)(3030);
|
|
44
|
-
|
|
62
|
+
fileServer = new server_1.FileServiceServer({
|
|
45
63
|
port: availablePort,
|
|
46
64
|
repoDir,
|
|
47
65
|
updateFile: false,
|
|
48
66
|
});
|
|
49
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");
|
|
50
71
|
await (0, test_run_1.runSingleTest)({
|
|
51
72
|
testName: "temp test",
|
|
52
73
|
suites: [],
|
|
@@ -63,7 +84,7 @@ async function runRecorder({ name }) {
|
|
|
63
84
|
const videoPaths = (0, upload_1.extractVideoAttachments)(repoDir);
|
|
64
85
|
let attachments = [];
|
|
65
86
|
if (videoPaths.length === 0) {
|
|
66
|
-
|
|
87
|
+
logger_1.logger.warn("No video attachments found for temp test");
|
|
67
88
|
}
|
|
68
89
|
else {
|
|
69
90
|
const videoUrls = await (0, upload_1.uploadVideosWithSpinner)(videoPaths, name);
|
|
@@ -75,11 +96,10 @@ async function runRecorder({ name }) {
|
|
|
75
96
|
await (0, pw_pause_1.revertToOriginalPwCode)(repoDir);
|
|
76
97
|
const codegenResult = fileServer.getCodegenSources();
|
|
77
98
|
await fileServer.stop();
|
|
78
|
-
const finalCode = await (0, display_1.displayResultsAndConfirm)(name, codegenResult);
|
|
79
99
|
await (0, request_1.sendToDashboardAsRequest)({
|
|
80
100
|
repoName,
|
|
81
101
|
testName: name,
|
|
82
|
-
codegenResult:
|
|
102
|
+
codegenResult: codegenResult,
|
|
83
103
|
attachments,
|
|
84
104
|
});
|
|
85
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,22 +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\`\`\``;
|
|
97
|
+
return [
|
|
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.`,
|
|
99
|
+
`Codegen result:`,
|
|
100
|
+
backtickedCodegenResult,
|
|
101
|
+
...attachments.map((attachment) => `[[${attachment}]]`),
|
|
102
|
+
].join("\n\n");
|
|
103
|
+
}
|
|
104
|
+
function defaultDescriptionForDisplay(codegenResult, attachments) {
|
|
105
|
+
const truncatedCodegenResult = truncateForDisplay(codegenResult, 74);
|
|
106
|
+
const backtickedCodegenResult = `\`\`\`\n${truncatedCodegenResult}\n\`\`\``;
|
|
7
107
|
return [
|
|
8
|
-
`To add this test, refer to the following code that
|
|
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.`,
|
|
9
109
|
`Codegen result:`,
|
|
10
|
-
|
|
11
|
-
`
|
|
12
|
-
...attachments,
|
|
110
|
+
backtickedCodegenResult,
|
|
111
|
+
...attachments.map((attachment) => `[[${attachment}]]`),
|
|
13
112
|
].join("\n\n");
|
|
14
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
|
+
}
|
|
15
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);
|
|
16
166
|
return createRequest({
|
|
17
167
|
repoName,
|
|
18
|
-
title
|
|
19
|
-
description
|
|
168
|
+
title,
|
|
169
|
+
description,
|
|
20
170
|
});
|
|
21
171
|
}
|
|
22
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":"
|
|
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"}
|
|
@@ -7,33 +7,33 @@ exports.createTempTestFile = createTempTestFile;
|
|
|
7
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(port) {
|
|
11
12
|
const tempFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
|
|
12
13
|
// Check if the temp file already exists
|
|
13
14
|
if (fs_1.default.existsSync(tempFilePath)) {
|
|
14
|
-
|
|
15
|
+
logger_1.logger.warn("Temporary test file already exists. Skipping creation.");
|
|
15
16
|
return;
|
|
16
17
|
}
|
|
17
18
|
// Create a basic test file
|
|
18
19
|
const content = `import { test, expect } from './fixtures';
|
|
19
20
|
|
|
20
21
|
test('temp test', async ({ page }) => {
|
|
21
|
-
await page.goto('
|
|
22
|
-
expect(await page.title()).toBe('Example Domain');
|
|
22
|
+
await page.goto('http://localhost:${port}/ready');
|
|
23
23
|
await recordTest(page);
|
|
24
24
|
});
|
|
25
25
|
`;
|
|
26
26
|
fs_1.default.writeFileSync(tempFilePath, content);
|
|
27
|
-
|
|
27
|
+
logger_1.logger.debug("Temporary test file created:", tempFilePath);
|
|
28
28
|
}
|
|
29
29
|
async function deleteTempTestFile() {
|
|
30
30
|
const tempFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
|
|
31
31
|
// Check if the temp file exists
|
|
32
32
|
if (fs_1.default.existsSync(tempFilePath)) {
|
|
33
33
|
fs_1.default.unlinkSync(tempFilePath);
|
|
34
|
-
|
|
34
|
+
logger_1.logger.debug("Temporary test file deleted:", tempFilePath);
|
|
35
35
|
}
|
|
36
36
|
else {
|
|
37
|
-
|
|
37
|
+
logger_1.logger.warn("Temporary test file does not exist. Skipping deletion.");
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/recorder/upload.ts"],"names":[],"mappings":"AAcA,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBjE;AA4DD,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAAE,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/recorder/upload.ts"],"names":[],"mappings":"AAcA,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBjE;AA4DD,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAAE,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC,CAc1B"}
|
package/dist/recorder/upload.js
CHANGED
|
@@ -79,7 +79,6 @@ async function uploadVideos(videoPaths, testSlug) {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
async function uploadVideosWithSpinner(videoPaths, testName) {
|
|
82
|
-
videoPaths.forEach((videoPath) => console.log(videoPath));
|
|
83
82
|
const uploadSpinner = (0, ora_1.default)("Uploading video recordings...").start();
|
|
84
83
|
try {
|
|
85
84
|
const slugifiedTestName = `${(0, slug_1.slugify)(testName)}-${Math.random().toString(36).substring(2, 8)}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empiricalrun/test-gen",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.69.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"@types/sanitize-html": "^2.11.0",
|
|
43
43
|
"async-retry": "^1.3.3",
|
|
44
44
|
"commander": "^12.1.0",
|
|
45
|
+
"console-log-level": "^1.4.1",
|
|
45
46
|
"detect-port": "^1.6.1",
|
|
46
47
|
"dotenv": "^16.4.5",
|
|
47
48
|
"eslint": "^8.57.0",
|
|
@@ -63,13 +64,14 @@
|
|
|
63
64
|
"tsx": "^4.16.2",
|
|
64
65
|
"typescript": "^5.3.3",
|
|
65
66
|
"zod": "^3.23.8",
|
|
66
|
-
"@empiricalrun/llm": "^0.
|
|
67
|
+
"@empiricalrun/llm": "^0.19.0",
|
|
67
68
|
"@empiricalrun/r2-uploader": "^0.3.9",
|
|
68
|
-
"@empiricalrun/test-run": "^0.10.
|
|
69
|
+
"@empiricalrun/test-run": "^0.10.5"
|
|
69
70
|
},
|
|
70
71
|
"devDependencies": {
|
|
71
72
|
"@playwright/test": "1.53.0",
|
|
72
73
|
"@types/async-retry": "^1.4.8",
|
|
74
|
+
"@types/console-log-level": "^1.4.5",
|
|
73
75
|
"@types/detect-port": "^1.3.5",
|
|
74
76
|
"@types/express": "^4.17.21",
|
|
75
77
|
"@types/js-levenshtein": "^1.1.3",
|
|
@@ -80,7 +82,7 @@
|
|
|
80
82
|
"playwright": "1.53.0",
|
|
81
83
|
"serve-handler": "^6.1.6",
|
|
82
84
|
"ts-patch": "^3.3.0",
|
|
83
|
-
"@empiricalrun/shared-types": "0.
|
|
85
|
+
"@empiricalrun/shared-types": "0.6.0"
|
|
84
86
|
},
|
|
85
87
|
"scripts": {
|
|
86
88
|
"dev": "tspc --build --watch",
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/index.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/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
|
-
}
|