@nbakka/mcp-appium 3.0.21 → 3.0.23
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/app_context.txt +3 -12
- package/lib/server.js +121 -0
- package/package.json +1 -1
package/lib/app_context.txt
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
Use mobile-mcp.
|
|
3
3
|
Navigate and explore the Housing app using the provided deeplink to validate, refine, and update the existing rough test scenarios.
|
|
4
4
|
If the app cannot be navigated for a certain scenario (e.g., UI element not reachable, deeplink not loading, or navigation gets stuck), then generate the test cases based on the partial understanding achieved + standard expected Housing app behavior.
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Don't generate new test cases beyond the provided rough scenarios.
|
|
6
|
+
Only modify test scenarios if there are discrepancies found during exploration.
|
|
7
|
+
Each test case should be detailed and structured as per the format below.
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* TEST CASE <number>:
|
|
@@ -22,16 +23,6 @@ Rewrite every rough test case into clean, modernized test cases using this struc
|
|
|
22
23
|
* - <expected result 2>
|
|
23
24
|
*/
|
|
24
25
|
|
|
25
|
-
Rules:
|
|
26
|
-
- Clean up, merge, and modernize outdated or rough test cases.
|
|
27
|
-
- Explore using mobile-mcp to verify flows and correct missing details.
|
|
28
|
-
- Always specify the exact order of UI elements (icons, tabs, instant links, buttons).
|
|
29
|
-
- When describing interactions, mention expected user-visible behavior (UI change, navigation, toggles, dialogs).
|
|
30
|
-
- If navigation is not fully possible, infer expected behavior and generate the most accurate test cases.
|
|
31
|
-
- Output only the test case blocks in the above format.
|
|
32
|
-
- Final output must be suitable for aicode.txt.
|
|
33
|
-
|
|
34
|
-
|
|
35
26
|
==========================
|
|
36
27
|
EXAMPLE (follow EXACT style)
|
|
37
28
|
==========================
|
package/lib/server.js
CHANGED
|
@@ -215,6 +215,127 @@ const createMcpServer = () => {
|
|
|
215
215
|
// }
|
|
216
216
|
// );
|
|
217
217
|
|
|
218
|
+
// Tool 1: Fetch incomplete test case
|
|
219
|
+
tool(
|
|
220
|
+
"mobile_fetch_incomplete_testcase",
|
|
221
|
+
"Fetches the first test case from a Google Sheet that has blank test steps but has a value in 'UT v/s Automation' column. Returns the test scenario and row number for later update.",
|
|
222
|
+
{
|
|
223
|
+
sheetName: zod_1.z.string().describe("The name of the Google Sheet tab to fetch test case data from").default("TestCases"),
|
|
224
|
+
},
|
|
225
|
+
async ({ sheetName }) => {
|
|
226
|
+
try {
|
|
227
|
+
// Load Google Sheets credentials
|
|
228
|
+
const keyFile = path.join(os.homedir(), 'Desktop', 'secret.json');
|
|
229
|
+
|
|
230
|
+
const auth = new google.auth.GoogleAuth({
|
|
231
|
+
keyFile,
|
|
232
|
+
scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly'],
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
const authClient = await auth.getClient();
|
|
236
|
+
const sheets = google.sheets({ version: 'v4', auth: authClient });
|
|
237
|
+
const spreadsheetId = '1jAilVUeQW99JUYj1KL4jovoxeWGUnsIcY_nMJR5H6dc';
|
|
238
|
+
|
|
239
|
+
const range = `${sheetName}!A1:Z1000`;
|
|
240
|
+
const res = await sheets.spreadsheets.values.get({ spreadsheetId, range });
|
|
241
|
+
const rows = res.data.values;
|
|
242
|
+
|
|
243
|
+
if (!rows || rows.length === 0) {
|
|
244
|
+
return `Sheet "${sheetName}" is empty or does not exist.`;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Map headers (trimmed, case-sensitive)
|
|
248
|
+
const header = rows[0].map(h => h.toString().trim());
|
|
249
|
+
|
|
250
|
+
// Find required column indices
|
|
251
|
+
const testCasesIdx = header.indexOf('Testcases');
|
|
252
|
+
const testStepsIdx = header.indexOf('Test Steps');
|
|
253
|
+
const utVsAutomationIdx = header.indexOf('UT v/s Automation');
|
|
254
|
+
|
|
255
|
+
if (testCasesIdx === -1 || testStepsIdx === -1 || utVsAutomationIdx === -1) {
|
|
256
|
+
return `Required columns "Testcases", "Test Steps", and/or "UT v/s Automation" not found in sheet "${sheetName}". Available columns: ${header.join(', ')}`;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Find first row with empty test steps and non-empty UT v/s Automation
|
|
260
|
+
for (let i = 1; i < rows.length; i++) {
|
|
261
|
+
const row = rows[i];
|
|
262
|
+
const testSteps = row[testStepsIdx] ? row[testStepsIdx].toString().trim() : '';
|
|
263
|
+
const utVsAutomation = row[utVsAutomationIdx] ? row[utVsAutomationIdx].toString().trim() : '';
|
|
264
|
+
const testScenario = row[testCasesIdx] ? row[testCasesIdx].toString().trim() : '';
|
|
265
|
+
|
|
266
|
+
// Check if test steps are empty, UT v/s Automation is not empty, and test scenario exists
|
|
267
|
+
if (!testSteps && utVsAutomation && testScenario) {
|
|
268
|
+
// Convert column index to letter (A, B, C, etc.)
|
|
269
|
+
const columnLetter = String.fromCharCode(65 + testStepsIdx);
|
|
270
|
+
const rowNumber = i + 1; // +1 because spreadsheet rows are 1-indexed
|
|
271
|
+
|
|
272
|
+
return JSON.stringify({
|
|
273
|
+
testScenario: testScenario,
|
|
274
|
+
sheetName: sheetName,
|
|
275
|
+
rowNumber: rowNumber,
|
|
276
|
+
columnLetter: columnLetter,
|
|
277
|
+
cellReference: `${columnLetter}${rowNumber}`
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return `No test cases found with blank test steps and non-empty "UT v/s Automation" in sheet "${sheetName}".`;
|
|
283
|
+
|
|
284
|
+
} catch (error) {
|
|
285
|
+
return `Error fetching incomplete test case: ${error.message}`;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
// Tool 2: Update Test Steps
|
|
291
|
+
tool(
|
|
292
|
+
"mobile_update_test_steps",
|
|
293
|
+
"Updates the Test Steps cell in Google Sheet for a specific test case. Use the sheetName, rowNumber, and columnLetter obtained from mobile_fetch_incomplete_testcase tool.",
|
|
294
|
+
{
|
|
295
|
+
sheetName: zod_1.z.string().describe("The name of the Google Sheet tab"),
|
|
296
|
+
rowNumber: zod_1.z.number().describe("The row number to update (from fetch tool)"),
|
|
297
|
+
columnLetter: zod_1.z.string().describe("The column letter for Test Steps (from fetch tool)"),
|
|
298
|
+
testSteps: zod_1.z.string().describe("The test steps content to write into the cell"),
|
|
299
|
+
},
|
|
300
|
+
async ({ sheetName, rowNumber, columnLetter, testSteps }) => {
|
|
301
|
+
try {
|
|
302
|
+
// Load Google Sheets credentials with write permissions
|
|
303
|
+
const keyFile = path.join(os.homedir(), 'Desktop', 'secret.json');
|
|
304
|
+
|
|
305
|
+
const auth = new google.auth.GoogleAuth({
|
|
306
|
+
keyFile,
|
|
307
|
+
scopes: ['https://www.googleapis.com/auth/spreadsheets'], // Full read/write access
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
const authClient = await auth.getClient();
|
|
311
|
+
const sheets = google.sheets({ version: 'v4', auth: authClient });
|
|
312
|
+
const spreadsheetId = '1jAilVUeQW99JUYj1KL4jovoxeWGUnsIcY_nMJR5H6dc';
|
|
313
|
+
|
|
314
|
+
// Construct the cell reference (e.g., "TestCases!C5")
|
|
315
|
+
const cellReference = `${sheetName}!${columnLetter}${rowNumber}`;
|
|
316
|
+
|
|
317
|
+
// Update the cell
|
|
318
|
+
const updateRes = await sheets.spreadsheets.values.update({
|
|
319
|
+
spreadsheetId,
|
|
320
|
+
range: cellReference,
|
|
321
|
+
valueInputOption: 'RAW',
|
|
322
|
+
resource: {
|
|
323
|
+
values: [[testSteps]]
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
if (updateRes.status === 200) {
|
|
328
|
+
return `Successfully updated Test Steps at ${cellReference} with content: "${testSteps.substring(0, 100)}${testSteps.length > 100 ? '...' : ''}"`;
|
|
329
|
+
} else {
|
|
330
|
+
return `Failed to update Test Steps. Status: ${updateRes.status}`;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
} catch (error) {
|
|
334
|
+
return `Error updating test steps: ${error.message}`;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
|
|
218
339
|
tool(
|
|
219
340
|
"mobile_learn_testcases_generation_context",
|
|
220
341
|
"Reads previously saved app context notes and returns them so they can be used to validate or update test cases. This should be executed before generating manual test cases.",
|