@nbakka/mcp-appium 2.0.89 → 2.0.90
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/lib/review-ui/index.html +318 -49
- package/lib/server.js +42 -48
- package/package.json +1 -1
package/lib/review-ui/index.html
CHANGED
|
@@ -3,26 +3,175 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title>Test Case Review</title>
|
|
6
|
+
<title>Test Case Review & Approval</title>
|
|
7
7
|
<style>
|
|
8
|
-
body {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
body {
|
|
9
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
10
|
+
margin: 0;
|
|
11
|
+
padding: 20px;
|
|
12
|
+
background-color: #f5f5f5;
|
|
13
|
+
line-height: 1.6;
|
|
14
|
+
}
|
|
15
|
+
.container {
|
|
16
|
+
max-width: 1200px;
|
|
17
|
+
margin: 0 auto;
|
|
18
|
+
background: white;
|
|
19
|
+
padding: 30px;
|
|
20
|
+
border-radius: 12px;
|
|
21
|
+
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
|
22
|
+
}
|
|
23
|
+
.section {
|
|
24
|
+
margin-bottom: 30px;
|
|
25
|
+
padding: 25px;
|
|
26
|
+
border: 2px solid #ddd;
|
|
27
|
+
border-radius: 8px;
|
|
28
|
+
position: relative;
|
|
29
|
+
}
|
|
30
|
+
.section h2 {
|
|
31
|
+
margin-top: 0;
|
|
32
|
+
margin-bottom: 20px;
|
|
33
|
+
padding-bottom: 10px;
|
|
34
|
+
border-bottom: 2px solid;
|
|
35
|
+
}
|
|
36
|
+
.new {
|
|
37
|
+
background-color: #e8f5e8;
|
|
38
|
+
border-color: #4caf50;
|
|
39
|
+
}
|
|
40
|
+
.new h2 { border-bottom-color: #4caf50; color: #2e7d32; }
|
|
41
|
+
.modify {
|
|
42
|
+
background-color: #fff8e1;
|
|
43
|
+
border-color: #ff9800;
|
|
44
|
+
}
|
|
45
|
+
.modify h2 { border-bottom-color: #ff9800; color: #f57c00; }
|
|
46
|
+
.remove {
|
|
47
|
+
background-color: #ffebee;
|
|
48
|
+
border-color: #f44336;
|
|
49
|
+
}
|
|
50
|
+
.remove h2 { border-bottom-color: #f44336; color: #c62828; }
|
|
51
|
+
.test-case {
|
|
52
|
+
margin: 15px 0;
|
|
53
|
+
padding: 20px;
|
|
54
|
+
background: white;
|
|
55
|
+
border-radius: 6px;
|
|
56
|
+
border: 1px solid #e0e0e0;
|
|
57
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
|
|
58
|
+
}
|
|
59
|
+
.test-case-header {
|
|
60
|
+
display: flex;
|
|
61
|
+
justify-content: space-between;
|
|
62
|
+
align-items: center;
|
|
63
|
+
margin-bottom: 15px;
|
|
64
|
+
}
|
|
65
|
+
.test-case-id {
|
|
66
|
+
font-weight: bold;
|
|
67
|
+
color: #666;
|
|
68
|
+
font-size: 0.9em;
|
|
69
|
+
}
|
|
70
|
+
.edit-btn, .save-btn, .cancel-btn-inline {
|
|
71
|
+
padding: 6px 12px;
|
|
72
|
+
border: none;
|
|
73
|
+
border-radius: 4px;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
font-size: 0.85em;
|
|
76
|
+
margin-left: 5px;
|
|
77
|
+
}
|
|
78
|
+
.edit-btn {
|
|
79
|
+
background-color: #2196f3;
|
|
80
|
+
color: white;
|
|
81
|
+
}
|
|
82
|
+
.save-btn {
|
|
83
|
+
background-color: #4caf50;
|
|
84
|
+
color: white;
|
|
85
|
+
}
|
|
86
|
+
.cancel-btn-inline {
|
|
87
|
+
background-color: #757575;
|
|
88
|
+
color: white;
|
|
89
|
+
}
|
|
90
|
+
.original-text {
|
|
91
|
+
color: #999;
|
|
92
|
+
text-decoration: line-through;
|
|
93
|
+
font-style: italic;
|
|
94
|
+
margin-bottom: 10px;
|
|
95
|
+
}
|
|
96
|
+
.modified-text {
|
|
97
|
+
color: #000;
|
|
98
|
+
font-weight: 500;
|
|
99
|
+
}
|
|
100
|
+
.editable-area {
|
|
101
|
+
width: 100%;
|
|
102
|
+
min-height: 60px;
|
|
103
|
+
padding: 10px;
|
|
104
|
+
border: 2px solid #ddd;
|
|
105
|
+
border-radius: 4px;
|
|
106
|
+
font-family: inherit;
|
|
107
|
+
font-size: 14px;
|
|
108
|
+
resize: vertical;
|
|
109
|
+
}
|
|
110
|
+
.editable-area:focus {
|
|
111
|
+
outline: none;
|
|
112
|
+
border-color: #2196f3;
|
|
113
|
+
}
|
|
114
|
+
.button-container {
|
|
115
|
+
text-align: center;
|
|
116
|
+
margin-top: 40px;
|
|
117
|
+
padding-top: 30px;
|
|
118
|
+
border-top: 2px solid #eee;
|
|
119
|
+
}
|
|
120
|
+
.main-button {
|
|
121
|
+
padding: 15px 30px;
|
|
122
|
+
margin: 0 15px;
|
|
123
|
+
border: none;
|
|
124
|
+
border-radius: 8px;
|
|
125
|
+
cursor: pointer;
|
|
126
|
+
font-size: 16px;
|
|
127
|
+
font-weight: 600;
|
|
128
|
+
text-transform: uppercase;
|
|
129
|
+
letter-spacing: 0.5px;
|
|
130
|
+
transition: all 0.3s ease;
|
|
131
|
+
}
|
|
132
|
+
.approve {
|
|
133
|
+
background-color: #4caf50;
|
|
134
|
+
color: white;
|
|
135
|
+
}
|
|
136
|
+
.approve:hover {
|
|
137
|
+
background-color: #45a049;
|
|
138
|
+
transform: translateY(-2px);
|
|
139
|
+
}
|
|
140
|
+
.cancel {
|
|
141
|
+
background-color: #f44336;
|
|
142
|
+
color: white;
|
|
143
|
+
}
|
|
144
|
+
.cancel:hover {
|
|
145
|
+
background-color: #da190b;
|
|
146
|
+
transform: translateY(-2px);
|
|
147
|
+
}
|
|
148
|
+
.status {
|
|
149
|
+
margin-top: 20px;
|
|
150
|
+
padding: 15px;
|
|
151
|
+
border-radius: 6px;
|
|
152
|
+
text-align: center;
|
|
153
|
+
font-weight: 500;
|
|
154
|
+
}
|
|
155
|
+
.status.success { background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; }
|
|
156
|
+
.status.error { background-color: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }
|
|
157
|
+
.status.info { background-color: #d1ecf1; color: #0c5460; border: 1px solid #bee5eb; }
|
|
158
|
+
#loading {
|
|
159
|
+
text-align: center;
|
|
160
|
+
padding: 50px;
|
|
161
|
+
font-size: 18px;
|
|
162
|
+
color: #666;
|
|
163
|
+
}
|
|
164
|
+
.empty-section {
|
|
165
|
+
text-align: center;
|
|
166
|
+
color: #999;
|
|
167
|
+
font-style: italic;
|
|
168
|
+
padding: 30px;
|
|
169
|
+
}
|
|
21
170
|
</style>
|
|
22
171
|
</head>
|
|
23
172
|
<body>
|
|
24
173
|
<div class="container">
|
|
25
|
-
<h1>Test Case Review</h1>
|
|
174
|
+
<h1>Test Case Review & Approval</h1>
|
|
26
175
|
<div id="loading">Loading test cases...</div>
|
|
27
176
|
<div id="content" style="display: none;">
|
|
28
177
|
<div id="new-section" class="section new">
|
|
@@ -37,9 +186,10 @@
|
|
|
37
186
|
<h2>Test Cases to Remove</h2>
|
|
38
187
|
<div id="remove-cases"></div>
|
|
39
188
|
</div>
|
|
40
|
-
<div
|
|
41
|
-
<button class="approve" onclick="
|
|
42
|
-
<button class="cancel" onclick="
|
|
189
|
+
<div class="button-container">
|
|
190
|
+
<button class="main-button approve" onclick="approveTestCases()">✓ Approve Test Cases</button>
|
|
191
|
+
<button class="main-button cancel" onclick="cancelReview()">✗ Cancel Review</button>
|
|
192
|
+
<div id="status" class="status" style="display: none;"></div>
|
|
43
193
|
</div>
|
|
44
194
|
</div>
|
|
45
195
|
</div>
|
|
@@ -47,10 +197,14 @@
|
|
|
47
197
|
<script>
|
|
48
198
|
let sessionId;
|
|
49
199
|
let testCases;
|
|
200
|
+
let editingStates = {};
|
|
50
201
|
|
|
51
202
|
async function loadTestCases() {
|
|
52
203
|
try {
|
|
53
204
|
const response = await fetch('/api/testcases');
|
|
205
|
+
if (!response.ok) {
|
|
206
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
207
|
+
}
|
|
54
208
|
const data = await response.json();
|
|
55
209
|
sessionId = data.sessionId;
|
|
56
210
|
testCases = data.testCases;
|
|
@@ -60,71 +214,186 @@
|
|
|
60
214
|
|
|
61
215
|
renderTestCases();
|
|
62
216
|
} catch (error) {
|
|
63
|
-
document.getElementById('loading').innerHTML =
|
|
217
|
+
document.getElementById('loading').innerHTML = `<div class="status error">Error loading test cases: ${error.message}</div>`;
|
|
64
218
|
}
|
|
65
219
|
}
|
|
66
220
|
|
|
67
221
|
function renderTestCases() {
|
|
68
|
-
|
|
69
|
-
|
|
222
|
+
renderNewCases();
|
|
223
|
+
renderModifyCases();
|
|
224
|
+
renderRemoveCases();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function renderNewCases() {
|
|
228
|
+
const container = document.getElementById('new-cases');
|
|
70
229
|
if (testCases.new && testCases.new.length > 0) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
230
|
+
container.innerHTML = testCases.new.map((tc, index) => `
|
|
231
|
+
<div class="test-case">
|
|
232
|
+
<div class="test-case-header">
|
|
233
|
+
<span class="test-case-id">ID: ${tc.id}</span>
|
|
234
|
+
<button class="edit-btn" onclick="toggleEdit('new', ${index})">Edit</button>
|
|
235
|
+
</div>
|
|
236
|
+
<div id="new-${index}-display" style="display: block;">
|
|
237
|
+
<strong>Description:</strong> ${tc.description}
|
|
238
|
+
</div>
|
|
239
|
+
<div id="new-${index}-edit" style="display: none;">
|
|
240
|
+
<label><strong>Description:</strong></label>
|
|
241
|
+
<textarea class="editable-area" id="new-${index}-desc">${tc.description}</textarea>
|
|
242
|
+
<div style="margin-top: 10px;">
|
|
243
|
+
<button class="save-btn" onclick="saveEdit('new', ${index})">Save</button>
|
|
244
|
+
<button class="cancel-btn-inline" onclick="cancelEdit('new', ${index})">Cancel</button>
|
|
245
|
+
</div>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
`).join('');
|
|
74
249
|
} else {
|
|
75
|
-
|
|
250
|
+
container.innerHTML = '<div class="empty-section">No new test cases</div>';
|
|
76
251
|
}
|
|
252
|
+
}
|
|
77
253
|
|
|
78
|
-
|
|
79
|
-
const
|
|
254
|
+
function renderModifyCases() {
|
|
255
|
+
const container = document.getElementById('modify-cases');
|
|
80
256
|
if (testCases.modify && testCases.modify.length > 0) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
<
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
257
|
+
container.innerHTML = testCases.modify.map((tc, index) => `
|
|
258
|
+
<div class="test-case">
|
|
259
|
+
<div class="test-case-header">
|
|
260
|
+
<span class="test-case-id">ID: ${tc.id}</span>
|
|
261
|
+
<button class="edit-btn" onclick="toggleEdit('modify', ${index})">Edit</button>
|
|
262
|
+
</div>
|
|
263
|
+
<div id="modify-${index}-display" style="display: block;">
|
|
264
|
+
<div class="original-text"><strong>Original:</strong> ${tc.original}</div>
|
|
265
|
+
<div class="modified-text"><strong>Modified:</strong> ${tc.modified}</div>
|
|
266
|
+
</div>
|
|
267
|
+
<div id="modify-${index}-edit" style="display: none;">
|
|
268
|
+
<label><strong>Original:</strong></label>
|
|
269
|
+
<textarea class="editable-area" id="modify-${index}-orig" readonly style="background-color: #f5f5f5;">${tc.original}</textarea>
|
|
270
|
+
<label style="margin-top: 10px; display: block;"><strong>Modified:</strong></label>
|
|
271
|
+
<textarea class="editable-area" id="modify-${index}-mod">${tc.modified}</textarea>
|
|
272
|
+
<div style="margin-top: 10px;">
|
|
273
|
+
<button class="save-btn" onclick="saveEdit('modify', ${index})">Save</button>
|
|
274
|
+
<button class="cancel-btn-inline" onclick="cancelEdit('modify', ${index})">Cancel</button>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
`).join('');
|
|
88
279
|
} else {
|
|
89
|
-
|
|
280
|
+
container.innerHTML = '<div class="empty-section">No modified test cases</div>';
|
|
90
281
|
}
|
|
282
|
+
}
|
|
91
283
|
|
|
92
|
-
|
|
93
|
-
const
|
|
284
|
+
function renderRemoveCases() {
|
|
285
|
+
const container = document.getElementById('remove-cases');
|
|
94
286
|
if (testCases.remove && testCases.remove.length > 0) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
287
|
+
container.innerHTML = testCases.remove.map((tc, index) => `
|
|
288
|
+
<div class="test-case">
|
|
289
|
+
<div class="test-case-header">
|
|
290
|
+
<span class="test-case-id">ID: ${tc.id}</span>
|
|
291
|
+
</div>
|
|
292
|
+
<div>
|
|
293
|
+
<strong>Description:</strong> ${tc.description}
|
|
294
|
+
<div style="margin-top: 10px; color: #c62828; font-weight: 500;">
|
|
295
|
+
⚠️ This test case will be removed
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
298
|
+
</div>
|
|
299
|
+
`).join('');
|
|
98
300
|
} else {
|
|
99
|
-
|
|
301
|
+
container.innerHTML = '<div class="empty-section">No test cases to remove</div>';
|
|
100
302
|
}
|
|
101
303
|
}
|
|
102
304
|
|
|
103
|
-
|
|
305
|
+
function toggleEdit(type, index) {
|
|
306
|
+
const displayDiv = document.getElementById(`${type}-${index}-display`);
|
|
307
|
+
const editDiv = document.getElementById(`${type}-${index}-edit`);
|
|
308
|
+
|
|
309
|
+
if (displayDiv.style.display === 'block') {
|
|
310
|
+
displayDiv.style.display = 'none';
|
|
311
|
+
editDiv.style.display = 'block';
|
|
312
|
+
editingStates[`${type}-${index}`] = true;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function saveEdit(type, index) {
|
|
317
|
+
if (type === 'new') {
|
|
318
|
+
const newDesc = document.getElementById(`new-${index}-desc`).value.trim();
|
|
319
|
+
if (newDesc) {
|
|
320
|
+
testCases.new[index].description = newDesc;
|
|
321
|
+
}
|
|
322
|
+
} else if (type === 'modify') {
|
|
323
|
+
const newMod = document.getElementById(`modify-${index}-mod`).value.trim();
|
|
324
|
+
if (newMod) {
|
|
325
|
+
testCases.modify[index].modified = newMod;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
cancelEdit(type, index);
|
|
330
|
+
renderTestCases();
|
|
331
|
+
showStatus('Changes saved successfully!', 'success');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function cancelEdit(type, index) {
|
|
335
|
+
const displayDiv = document.getElementById(`${type}-${index}-display`);
|
|
336
|
+
const editDiv = document.getElementById(`${type}-${index}-edit`);
|
|
337
|
+
|
|
338
|
+
displayDiv.style.display = 'block';
|
|
339
|
+
editDiv.style.display = 'none';
|
|
340
|
+
delete editingStates[`${type}-${index}`];
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function showStatus(message, type) {
|
|
344
|
+
const statusDiv = document.getElementById('status');
|
|
345
|
+
statusDiv.textContent = message;
|
|
346
|
+
statusDiv.className = `status ${type}`;
|
|
347
|
+
statusDiv.style.display = 'block';
|
|
348
|
+
|
|
349
|
+
setTimeout(() => {
|
|
350
|
+
statusDiv.style.display = 'none';
|
|
351
|
+
}, 3000);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
async function approveTestCases() {
|
|
104
355
|
try {
|
|
356
|
+
showStatus('Processing approval...', 'info');
|
|
105
357
|
const response = await fetch(`/approve/${sessionId}`, {
|
|
106
358
|
method: 'POST',
|
|
107
359
|
headers: { 'Content-Type': 'application/json' },
|
|
108
360
|
body: JSON.stringify(testCases)
|
|
109
361
|
});
|
|
362
|
+
|
|
363
|
+
if (!response.ok) {
|
|
364
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
365
|
+
}
|
|
366
|
+
|
|
110
367
|
const result = await response.json();
|
|
111
|
-
|
|
112
|
-
|
|
368
|
+
showStatus(result.message || 'Test cases approved successfully!', 'success');
|
|
369
|
+
|
|
370
|
+
setTimeout(() => {
|
|
371
|
+
window.close();
|
|
372
|
+
}, 2000);
|
|
113
373
|
} catch (error) {
|
|
114
|
-
|
|
374
|
+
showStatus(`Error approving test cases: ${error.message}`, 'error');
|
|
115
375
|
}
|
|
116
376
|
}
|
|
117
377
|
|
|
118
|
-
async function
|
|
378
|
+
async function cancelReview() {
|
|
119
379
|
try {
|
|
380
|
+
showStatus('Cancelling review...', 'info');
|
|
120
381
|
const response = await fetch(`/cancel/${sessionId}`, {
|
|
121
382
|
method: 'POST'
|
|
122
383
|
});
|
|
384
|
+
|
|
385
|
+
if (!response.ok) {
|
|
386
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
387
|
+
}
|
|
388
|
+
|
|
123
389
|
const result = await response.json();
|
|
124
|
-
|
|
125
|
-
|
|
390
|
+
showStatus(result.message || 'Review cancelled', 'info');
|
|
391
|
+
|
|
392
|
+
setTimeout(() => {
|
|
393
|
+
window.close();
|
|
394
|
+
}, 2000);
|
|
126
395
|
} catch (error) {
|
|
127
|
-
|
|
396
|
+
showStatus(`Error cancelling review: ${error.message}`, 'error');
|
|
128
397
|
}
|
|
129
398
|
}
|
|
130
399
|
|
package/lib/server.js
CHANGED
|
@@ -809,48 +809,44 @@ tool(
|
|
|
809
809
|
const path = require('path');
|
|
810
810
|
const sessionId = Date.now().toString();
|
|
811
811
|
|
|
812
|
-
//
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
testCases.forEach((tc, index) => {
|
|
820
|
-
if (!tc || !Array.isArray(tc) || tc.length < 2) {
|
|
821
|
-
console.log(`Skipping invalid test case at index ${index}:`, tc);
|
|
822
|
-
return;
|
|
823
|
-
}
|
|
812
|
+
// Add the improved parseTestCases function here
|
|
813
|
+
function parseTestCases(testCasesArray) {
|
|
814
|
+
const parsed = {
|
|
815
|
+
new: [],
|
|
816
|
+
modify: [],
|
|
817
|
+
remove: []
|
|
818
|
+
};
|
|
824
819
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
})
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
} else {
|
|
848
|
-
console.log(`Unrecognized test case format at index ${index}:`, tc);
|
|
849
|
-
}
|
|
850
|
-
});
|
|
820
|
+
testCasesArray.forEach(tc => {
|
|
821
|
+
if (tc.length === 4 && tc[2] === 'Modify') {
|
|
822
|
+
// Modify: [original, modified, "Modify", tcmsId]
|
|
823
|
+
parsed.modify.push({
|
|
824
|
+
id: tc[3],
|
|
825
|
+
original: tc[0],
|
|
826
|
+
modified: tc[1]
|
|
827
|
+
});
|
|
828
|
+
} else if (tc.length === 3 && tc[1] === 'Remove') {
|
|
829
|
+
// Remove: [description, "Remove", tcmsId]
|
|
830
|
+
parsed.remove.push({
|
|
831
|
+
id: tc[2],
|
|
832
|
+
description: tc[0]
|
|
833
|
+
});
|
|
834
|
+
} else if (tc.length === 2 && tc[1] === 'New') {
|
|
835
|
+
// New: [description, "New"]
|
|
836
|
+
parsed.new.push({
|
|
837
|
+
description: tc[0],
|
|
838
|
+
id: `NEW-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
});
|
|
851
842
|
|
|
852
|
-
|
|
843
|
+
return parsed;
|
|
844
|
+
}
|
|
853
845
|
|
|
846
|
+
// Use the improved parsing function
|
|
847
|
+
const parsedTestCases = parseTestCases(testCases);
|
|
848
|
+
|
|
849
|
+
// Remove the old parsing logic and console.log statements that cause JSON errors
|
|
854
850
|
// Initialize session state
|
|
855
851
|
approvalSessions.set(sessionId, {
|
|
856
852
|
status: 'pending',
|
|
@@ -901,12 +897,12 @@ tool(
|
|
|
901
897
|
});
|
|
902
898
|
|
|
903
899
|
const server = app.listen(port, async () => {
|
|
904
|
-
console.log
|
|
900
|
+
// Remove console.log to prevent JSON parsing errors
|
|
905
901
|
try {
|
|
906
902
|
const { default: open } = await import('open');
|
|
907
903
|
await open(`http://localhost:${port}`);
|
|
908
904
|
} catch (openError) {
|
|
909
|
-
|
|
905
|
+
// Silent fail for browser opening
|
|
910
906
|
}
|
|
911
907
|
});
|
|
912
908
|
|
|
@@ -925,23 +921,21 @@ tool(
|
|
|
925
921
|
}
|
|
926
922
|
}, 300000);
|
|
927
923
|
|
|
928
|
-
|
|
924
|
+
// Return clean JSON response
|
|
925
|
+
return JSON.stringify({
|
|
929
926
|
status: "review_started",
|
|
930
927
|
sessionId: sessionId,
|
|
931
928
|
message: "Test case review interface opened in browser. Use check_approval_status tool to poll for approval.",
|
|
932
929
|
testCasesCount: testCases.length,
|
|
933
930
|
browserUrl: `http://localhost:${port}`,
|
|
934
931
|
instructions: "Poll every 25 seconds using check_approval_status tool until approved or timeout (5 minutes)"
|
|
935
|
-
};
|
|
936
|
-
|
|
937
|
-
return JSON.stringify(response);
|
|
932
|
+
});
|
|
938
933
|
|
|
939
934
|
} catch (err) {
|
|
940
|
-
|
|
935
|
+
return JSON.stringify({
|
|
941
936
|
status: "error",
|
|
942
937
|
message: `Error setting up review interface: ${err.message}`
|
|
943
|
-
};
|
|
944
|
-
return JSON.stringify(errorResponse);
|
|
938
|
+
});
|
|
945
939
|
}
|
|
946
940
|
}
|
|
947
941
|
);
|