@nbakka/mcp-appium 3.0.20 → 3.0.22
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 +68 -68
- 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
|
@@ -147,76 +147,76 @@ const createMcpServer = () => {
|
|
|
147
147
|
const fs = require('fs').promises;
|
|
148
148
|
const path = require('path');
|
|
149
149
|
|
|
150
|
-
tool(
|
|
151
|
-
"mobile_learn_current_app_context",
|
|
152
|
-
"Follow these instructions strictly to navigate through the app. This should be the first step after launching the app and before performing any tests. Google Sheet name to fetch locatorName and androidLocator from the specified sheet. NOTE: Only use the locator data from the Google Sheet at the end while generating test cases, don't use to navigate through screens",
|
|
153
|
-
{
|
|
154
|
-
sheetName: zod_1.z.string().describe("The name of the Google Sheet to fetch locator data from").default("PDP"),
|
|
155
|
-
},
|
|
156
|
-
async ({ sheetName }) => {
|
|
157
|
-
try {
|
|
158
|
-
// Read app context notes from file
|
|
159
|
-
const notesFilePath = path.join(__dirname, 'app_context.txt');
|
|
160
|
-
const fileContent = await fs.readFile(notesFilePath, 'utf-8');
|
|
161
|
-
|
|
162
|
-
const notes = fileContent
|
|
163
|
-
.split('\n')
|
|
164
|
-
.map(line => line.trim())
|
|
165
|
-
.filter(line => line.length > 0);
|
|
166
|
-
|
|
167
|
-
// Initialize response object
|
|
168
|
-
const context = { notes, locatorData: null };
|
|
169
|
-
|
|
170
|
-
if (sheetName && sheetName.trim() !== '') {
|
|
171
|
-
// Load Google Sheets credentials with keyFile option (no manual parse)
|
|
172
|
-
const keyFile = path.join(os.homedir(), 'Desktop', 'secret.json');
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
const auth = new google.auth.GoogleAuth({
|
|
176
|
-
keyFile,
|
|
177
|
-
scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly'],
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
const authClient = await auth.getClient();
|
|
181
|
-
const sheets = google.sheets({ version: 'v4', auth: authClient });
|
|
182
|
-
const spreadsheetId = '1UapR81AxaztDUlPGDV-_EwHo2hWXkKCZXl8ALsvIyxA';
|
|
183
|
-
|
|
184
|
-
const range = `${sheetName}!A1:Z1000`;
|
|
185
|
-
const res = await sheets.spreadsheets.values.get({ spreadsheetId, range });
|
|
186
|
-
const rows = res.data.values;
|
|
187
|
-
|
|
188
|
-
if (!rows || rows.length === 0) {
|
|
189
|
-
return `Sheet "${sheetName}" is empty or does not exist. Notes loaded: ${JSON.stringify(notes)}`;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Map headers exactly (trimmed, case-sensitive)
|
|
193
|
-
const header = rows[0].map(h => h.toString().trim());
|
|
194
|
-
|
|
195
|
-
const locatorNameIdx = header.indexOf('locatorName');
|
|
196
|
-
const androidLocatorIdx = header.indexOf('androidLocator');
|
|
197
|
-
|
|
198
|
-
if (locatorNameIdx === -1 || androidLocatorIdx === -1) {
|
|
199
|
-
return `Required columns "locatorName" and/or "androidLocator" not found in sheet "${sheetName}". Notes loaded: ${JSON.stringify(notes)}`;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const locatorData = rows.slice(1)
|
|
203
|
-
.filter(row => row[locatorNameIdx] && row[androidLocatorIdx])
|
|
204
|
-
.map(row => ({
|
|
205
|
-
locatorName: row[locatorNameIdx],
|
|
206
|
-
androidLocator: row[androidLocatorIdx],
|
|
207
|
-
}));
|
|
208
|
-
|
|
209
|
-
context.locatorData = locatorData;
|
|
210
|
-
}
|
|
211
|
-
return `App context learned: ${JSON.stringify(context)}`;
|
|
212
|
-
} catch (error) {
|
|
213
|
-
return `Error reading app context notes or fetching locator data: ${error.message}`;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
);
|
|
150
|
+
// tool(
|
|
151
|
+
// "mobile_learn_current_app_context",
|
|
152
|
+
// "Follow these instructions strictly to navigate through the app. This should be the first step after launching the app and before performing any tests. Google Sheet name to fetch locatorName and androidLocator from the specified sheet. NOTE: Only use the locator data from the Google Sheet at the end while generating test cases, don't use to navigate through screens",
|
|
153
|
+
// {
|
|
154
|
+
// sheetName: zod_1.z.string().describe("The name of the Google Sheet to fetch locator data from").default("PDP"),
|
|
155
|
+
// },
|
|
156
|
+
// async ({ sheetName }) => {
|
|
157
|
+
// try {
|
|
158
|
+
// // Read app context notes from file
|
|
159
|
+
// const notesFilePath = path.join(__dirname, 'app_context.txt');
|
|
160
|
+
// const fileContent = await fs.readFile(notesFilePath, 'utf-8');
|
|
161
|
+
//
|
|
162
|
+
// const notes = fileContent
|
|
163
|
+
// .split('\n')
|
|
164
|
+
// .map(line => line.trim())
|
|
165
|
+
// .filter(line => line.length > 0);
|
|
166
|
+
//
|
|
167
|
+
// // Initialize response object
|
|
168
|
+
// const context = { notes, locatorData: null };
|
|
169
|
+
//
|
|
170
|
+
// if (sheetName && sheetName.trim() !== '') {
|
|
171
|
+
// // Load Google Sheets credentials with keyFile option (no manual parse)
|
|
172
|
+
// const keyFile = path.join(os.homedir(), 'Desktop', 'secret.json');
|
|
173
|
+
//
|
|
174
|
+
//
|
|
175
|
+
// const auth = new google.auth.GoogleAuth({
|
|
176
|
+
// keyFile,
|
|
177
|
+
// scopes: ['https://www.googleapis.com/auth/spreadsheets.readonly'],
|
|
178
|
+
// });
|
|
179
|
+
//
|
|
180
|
+
// const authClient = await auth.getClient();
|
|
181
|
+
// const sheets = google.sheets({ version: 'v4', auth: authClient });
|
|
182
|
+
// const spreadsheetId = '1UapR81AxaztDUlPGDV-_EwHo2hWXkKCZXl8ALsvIyxA';
|
|
183
|
+
//
|
|
184
|
+
// const range = `${sheetName}!A1:Z1000`;
|
|
185
|
+
// const res = await sheets.spreadsheets.values.get({ spreadsheetId, range });
|
|
186
|
+
// const rows = res.data.values;
|
|
187
|
+
//
|
|
188
|
+
// if (!rows || rows.length === 0) {
|
|
189
|
+
// return `Sheet "${sheetName}" is empty or does not exist. Notes loaded: ${JSON.stringify(notes)}`;
|
|
190
|
+
// }
|
|
191
|
+
//
|
|
192
|
+
// // Map headers exactly (trimmed, case-sensitive)
|
|
193
|
+
// const header = rows[0].map(h => h.toString().trim());
|
|
194
|
+
//
|
|
195
|
+
// const locatorNameIdx = header.indexOf('locatorName');
|
|
196
|
+
// const androidLocatorIdx = header.indexOf('androidLocator');
|
|
197
|
+
//
|
|
198
|
+
// if (locatorNameIdx === -1 || androidLocatorIdx === -1) {
|
|
199
|
+
// return `Required columns "locatorName" and/or "androidLocator" not found in sheet "${sheetName}". Notes loaded: ${JSON.stringify(notes)}`;
|
|
200
|
+
// }
|
|
201
|
+
//
|
|
202
|
+
// const locatorData = rows.slice(1)
|
|
203
|
+
// .filter(row => row[locatorNameIdx] && row[androidLocatorIdx])
|
|
204
|
+
// .map(row => ({
|
|
205
|
+
// locatorName: row[locatorNameIdx],
|
|
206
|
+
// androidLocator: row[androidLocatorIdx],
|
|
207
|
+
// }));
|
|
208
|
+
//
|
|
209
|
+
// context.locatorData = locatorData;
|
|
210
|
+
// }
|
|
211
|
+
// return `App context learned: ${JSON.stringify(context)}`;
|
|
212
|
+
// } catch (error) {
|
|
213
|
+
// return `Error reading app context notes or fetching locator data: ${error.message}`;
|
|
214
|
+
// }
|
|
215
|
+
// }
|
|
216
|
+
// );
|
|
217
217
|
|
|
218
218
|
tool(
|
|
219
|
-
"
|
|
219
|
+
"mobile_learn_testcases_generation_context",
|
|
220
220
|
"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.",
|
|
221
221
|
{},
|
|
222
222
|
async () => {
|