@iflow-mcp/appiumtestdistribution-mcp-appium-gestures 1.0.0
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/6139_process.log +3 -0
- package/LICENSE +7 -0
- package/README.md +198 -0
- package/language.json +1 -0
- package/package.json +1 -0
- package/package_name +1 -0
- package/push_info.json +5 -0
- package/src/index.js +43 -0
- package/src/resources/double-tap-gesture.js +97 -0
- package/src/resources/drag-drop-gesture.js +91 -0
- package/src/resources/gesture-by-name.js +43 -0
- package/src/resources/index.js +21 -0
- package/src/resources/long-press-gesture.js +77 -0
- package/src/resources/pinch-zoom-gesture.js +112 -0
- package/src/resources/scroll-gesture.js +127 -0
- package/src/resources/swipe-gesture.js +118 -0
- package/src/resources/tap-gesture.js +79 -0
- package/src/server.js +19 -0
- package/src/tools/generate-double-tap-code.js +125 -0
- package/src/tools/generate-long-press-code.js +89 -0
- package/src/tools/generate-scroll-code.js +174 -0
- package/src/tools/generate-swipe-code.js +89 -0
- package/src/tools/generate-tap-code.js +97 -0
- package/src/tools/index.js +15 -0
package/6139_process.log
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2025 AppiumTestDistribution
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
[](https://mseep.ai/app/appiumtestdistribution-mcp-appium-gestures)
|
|
2
|
+
|
|
3
|
+
# MCP Appium Gestures
|
|
4
|
+
|
|
5
|
+
An MCP (Model Context Protocol) server providing resources and tools for Appium mobile gestures.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Documentation resources for common Appium mobile gestures:
|
|
10
|
+
|
|
11
|
+
- Tap
|
|
12
|
+
- Swipe
|
|
13
|
+
- Scroll
|
|
14
|
+
- Pinch/Zoom
|
|
15
|
+
- Long Press
|
|
16
|
+
- Drag and Drop
|
|
17
|
+
- Double Tap
|
|
18
|
+
|
|
19
|
+
- Tools to generate code for these gestures in different languages:
|
|
20
|
+
- JavaScript (WebdriverIO v9+ and below)
|
|
21
|
+
- Java (Appium Java Client)
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Clone the repository
|
|
27
|
+
git clone https://github.com/yourusername/mcp-appium-gestures.git
|
|
28
|
+
cd mcp-appium-gestures
|
|
29
|
+
|
|
30
|
+
# Install dependencies
|
|
31
|
+
npm install
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
### Start with stdio transport (for local use)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Start the server with stdio transport
|
|
40
|
+
npm start
|
|
41
|
+
# or
|
|
42
|
+
npm run start:stdio
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Start with SSE transport (for remote use)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Start the server with SSE transport on default port (8080)
|
|
49
|
+
npm run start:sse
|
|
50
|
+
|
|
51
|
+
# Start the server with SSE transport on a custom port
|
|
52
|
+
npm run start:sse:port 3000
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Development and Testing
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# Test with mcp-cli
|
|
59
|
+
npm run dev
|
|
60
|
+
|
|
61
|
+
# Inspect with MCP Inspector
|
|
62
|
+
npm run inspect
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Usage with Claude
|
|
66
|
+
|
|
67
|
+
To use this MCP server with Claude, you need to add it to your MCP settings configuration file. The location of this file depends on your platform:
|
|
68
|
+
|
|
69
|
+
- For Cursor: `/Users/[username]/Library/Application Support/Cursor/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`
|
|
70
|
+
- For Claude Desktop: `/Users/[username]/Library/Application Support/Claude/claude_desktop_config.json`
|
|
71
|
+
- For Cline or other MCP clients: Check your client's documentation for the configuration file location
|
|
72
|
+
|
|
73
|
+
Add the following configuration to the `mcpServers` object in the settings file:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"appium-gestures": {
|
|
79
|
+
"command": "npx",
|
|
80
|
+
"disabled": false,
|
|
81
|
+
"args": ["mcp-appium-gestures"],
|
|
82
|
+
"autoApprove": [],
|
|
83
|
+
"timeout": 300,
|
|
84
|
+
"transportType": "stdio"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Once configured, you can use the MCP server's tools and resources directly in Claude:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
<use_mcp_tool>
|
|
94
|
+
<server_name>appium-gestures</server_name>
|
|
95
|
+
<tool_name>generate-tap-code</tool_name>
|
|
96
|
+
<arguments>
|
|
97
|
+
{
|
|
98
|
+
"language": "javascript",
|
|
99
|
+
"useElement": true,
|
|
100
|
+
"elementId": "login-button"
|
|
101
|
+
}
|
|
102
|
+
</arguments>
|
|
103
|
+
</use_mcp_tool>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Or access resources:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
<access_mcp_resource>
|
|
110
|
+
<server_name>appium-gestures</server_name>
|
|
111
|
+
<uri>gesture://tap</uri>
|
|
112
|
+
</access_mcp_resource>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Resources
|
|
116
|
+
|
|
117
|
+
The server provides documentation resources for the following gestures:
|
|
118
|
+
|
|
119
|
+
- `gesture://tap` - Tap gesture documentation
|
|
120
|
+
- `gesture://swipe` - Swipe gesture documentation
|
|
121
|
+
- `gesture://scroll` - Scroll gesture documentation
|
|
122
|
+
- `gesture://pinch-zoom` - Pinch and zoom gestures documentation
|
|
123
|
+
- `gesture://long-press` - Long press gesture documentation
|
|
124
|
+
- `gesture://drag-drop` - Drag and drop gesture documentation
|
|
125
|
+
- `gesture://double-tap` - Double tap gesture documentation
|
|
126
|
+
|
|
127
|
+
You can also access a specific gesture by name using the template: `gesture://{name}`
|
|
128
|
+
|
|
129
|
+
## Tools
|
|
130
|
+
|
|
131
|
+
The server provides the following tools to generate code for Appium gestures:
|
|
132
|
+
|
|
133
|
+
### generate-tap-code
|
|
134
|
+
|
|
135
|
+
Generates code for tap gesture.
|
|
136
|
+
|
|
137
|
+
Parameters:
|
|
138
|
+
|
|
139
|
+
- `language`: 'javascript' or 'java'
|
|
140
|
+
- `useElement`: boolean - whether to tap on an element or at coordinates
|
|
141
|
+
- `elementId`: string (required if useElement is true) - the element ID to tap on
|
|
142
|
+
- `x`: number (required if useElement is false) - x coordinate to tap at
|
|
143
|
+
- `y`: number (required if useElement is false) - y coordinate to tap at
|
|
144
|
+
|
|
145
|
+
### generate-swipe-code
|
|
146
|
+
|
|
147
|
+
Generates code for swipe gesture.
|
|
148
|
+
|
|
149
|
+
Parameters:
|
|
150
|
+
|
|
151
|
+
- `language`: 'javascript' or 'java'
|
|
152
|
+
- `startX`: number - starting x coordinate
|
|
153
|
+
- `startY`: number - starting y coordinate
|
|
154
|
+
- `endX`: number - ending x coordinate
|
|
155
|
+
- `endY`: number - ending y coordinate
|
|
156
|
+
- `duration`: number (optional, default: 500) - duration of the swipe in milliseconds
|
|
157
|
+
|
|
158
|
+
### generate-scroll-code
|
|
159
|
+
|
|
160
|
+
Generates code for scroll gesture.
|
|
161
|
+
|
|
162
|
+
Parameters:
|
|
163
|
+
|
|
164
|
+
- `language`: 'javascript' or 'java'
|
|
165
|
+
- `direction`: 'up', 'down', 'left', or 'right'
|
|
166
|
+
- `useElement`: boolean (optional, default: false) - whether to scroll to an element
|
|
167
|
+
- `elementId`: string (optional) - the element ID to scroll to
|
|
168
|
+
- `distance`: number (optional, default: 300) - distance to scroll
|
|
169
|
+
|
|
170
|
+
### generate-long-press-code
|
|
171
|
+
|
|
172
|
+
Generates code for long press gesture.
|
|
173
|
+
|
|
174
|
+
Parameters:
|
|
175
|
+
|
|
176
|
+
- `language`: 'javascript' or 'java'
|
|
177
|
+
- `useElement`: boolean - whether to long press on an element or at coordinates
|
|
178
|
+
- `elementId`: string (required if useElement is true) - the element ID to long press on
|
|
179
|
+
- `x`: number (required if useElement is false) - x coordinate to long press at
|
|
180
|
+
- `y`: number (required if useElement is false) - y coordinate to long press at
|
|
181
|
+
- `duration`: number (optional, default: 2000) - duration of the long press in milliseconds
|
|
182
|
+
|
|
183
|
+
### generate-double-tap-code
|
|
184
|
+
|
|
185
|
+
Generates code for double tap gesture.
|
|
186
|
+
|
|
187
|
+
Parameters:
|
|
188
|
+
|
|
189
|
+
- `language`: 'javascript' or 'java'
|
|
190
|
+
- `useElement`: boolean - whether to double tap on an element or at coordinates
|
|
191
|
+
- `elementId`: string (required if useElement is true) - the element ID to double tap on
|
|
192
|
+
- `x`: number (required if useElement is false) - x coordinate to double tap at
|
|
193
|
+
- `y`: number (required if useElement is false) - y coordinate to double tap at
|
|
194
|
+
- `pauseDuration`: number (optional, default: 200) - pause duration between taps in milliseconds
|
|
195
|
+
|
|
196
|
+
## License
|
|
197
|
+
|
|
198
|
+
MIT
|
package/language.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nodejs
|
package/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name": "@iflow-mcp/appiumtestdistribution-mcp-appium-gestures", "version": "1.0.0", "type": "module", "main": "src/index.js", "bin": {"iflow-mcp-appiumtestdistribution-mcp-appium-gestures": "src/index.js"}, "scripts": {"start": "node src/index.js", "start:stdio": "node src/index.js", "start:sse": "node src/index.js --sse", "start:sse:port": "node src/index.js --sse --port=", "dev": "npx fastmcp dev src/index.js", "inspect": "npx fastmcp inspect src/index.js", "test": "echo \"Error: no test specified\" && exit 1"}, "author": "", "license": "MIT", "description": "MCP server providing resources and tools for Appium mobile gestures", "dependencies": {"@modelcontextprotocol/sdk": "^1.11.0", "fastmcp": "^1.23.2", "zod": "^3.24.3"}}
|
package/package_name
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@iflow-mcp/appiumtestdistribution-mcp-appium-gestures
|
package/push_info.json
ADDED
package/src/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import server from './server.js';
|
|
4
|
+
|
|
5
|
+
// Parse command line arguments
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
const useSSE = args.includes('--sse');
|
|
8
|
+
const port = args.find((arg) => arg.startsWith('--port='))?.split('=')[1] || '8080';
|
|
9
|
+
|
|
10
|
+
// Start the server with the appropriate transport
|
|
11
|
+
async function startServer() {
|
|
12
|
+
console.log("Starting Appium Gestures MCP Server...");
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
if (useSSE) {
|
|
16
|
+
// Start with SSE transport
|
|
17
|
+
server.start({
|
|
18
|
+
transportType: 'sse',
|
|
19
|
+
sse: {
|
|
20
|
+
endpoint: '/sse',
|
|
21
|
+
port: parseInt(port, 10),
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
console.log(`Server started with SSE transport on http://localhost:${port}/sse`);
|
|
26
|
+
console.log("Waiting for client connections...");
|
|
27
|
+
} else {
|
|
28
|
+
// Start with stdio transport
|
|
29
|
+
server.start({
|
|
30
|
+
transportType: 'stdio',
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
console.log("Server started with stdio transport");
|
|
34
|
+
console.log("Waiting for client connections...");
|
|
35
|
+
}
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error("Error starting server:", error);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Start the server
|
|
43
|
+
startServer();
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource for double tap gesture documentation
|
|
3
|
+
*/
|
|
4
|
+
export default function doubleTapGesture(server) {
|
|
5
|
+
server.addResource({
|
|
6
|
+
uri: 'gesture://double-tap',
|
|
7
|
+
name: 'Double Tap Gesture',
|
|
8
|
+
mimeType: 'text/markdown',
|
|
9
|
+
async load() {
|
|
10
|
+
return {
|
|
11
|
+
text: `
|
|
12
|
+
# Double Tap Gesture in Appium
|
|
13
|
+
|
|
14
|
+
The double tap gesture simulates tapping twice in quick succession on the same location, commonly used for zooming in on maps or images.
|
|
15
|
+
|
|
16
|
+
## WebdriverIO Example (v9+)
|
|
17
|
+
\`\`\`javascript
|
|
18
|
+
// Double tap on an element
|
|
19
|
+
// Note: In WebdriverIO v9+, you can use the doubleClick method
|
|
20
|
+
const element = $('~element-id');
|
|
21
|
+
await element.doubleClick();
|
|
22
|
+
\`\`\`
|
|
23
|
+
|
|
24
|
+
## WebdriverIO Example (below v9)
|
|
25
|
+
\`\`\`javascript
|
|
26
|
+
// Double tap at specific coordinates using touchAction
|
|
27
|
+
await driver.touchAction([
|
|
28
|
+
{ action: 'tap', x: 100, y: 200 },
|
|
29
|
+
{ action: 'wait', ms: 100 },
|
|
30
|
+
{ action: 'tap', x: 100, y: 200 }
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
// Using the Gestures helper class
|
|
34
|
+
const { x, y } = await element.getLocation();
|
|
35
|
+
const centerX = x + (await element.getSize()).width / 2;
|
|
36
|
+
const centerY = y + (await element.getSize()).height / 2;
|
|
37
|
+
|
|
38
|
+
// Execute double tap gesture
|
|
39
|
+
await driver
|
|
40
|
+
.action('pointer')
|
|
41
|
+
.move(centerX, centerY)
|
|
42
|
+
.down()
|
|
43
|
+
.up()
|
|
44
|
+
.pause(100)
|
|
45
|
+
.down()
|
|
46
|
+
.up()
|
|
47
|
+
.perform();
|
|
48
|
+
\`\`\`
|
|
49
|
+
|
|
50
|
+
## Appium Java Client Example
|
|
51
|
+
\`\`\`java
|
|
52
|
+
// Implementation from VodQaAdvancedAppium repository
|
|
53
|
+
@Test
|
|
54
|
+
public void doubleTap() throws InterruptedException {
|
|
55
|
+
// Setup
|
|
56
|
+
login();
|
|
57
|
+
Thread.sleep(5000);
|
|
58
|
+
driver.findElement(AppiumBy.accessibilityId("doubleTap")).click();
|
|
59
|
+
|
|
60
|
+
// Get the element to double tap
|
|
61
|
+
WebElement element = new WebDriverWait(driver, Duration.ofMillis(30))
|
|
62
|
+
.until(elementToBeClickable(AppiumBy.accessibilityId("doubleTapMe")));
|
|
63
|
+
|
|
64
|
+
// Get element location
|
|
65
|
+
Point source = element.getLocation();
|
|
66
|
+
|
|
67
|
+
// Create finger gesture with touch pointer
|
|
68
|
+
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
|
|
69
|
+
Sequence tap = new Sequence(finger, 1);
|
|
70
|
+
|
|
71
|
+
// First tap
|
|
72
|
+
tap.addAction(finger.createPointerMove(Duration.ofMillis(0),
|
|
73
|
+
PointerInput.Origin.viewport(), source.x, source.y));
|
|
74
|
+
tap.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
|
|
75
|
+
tap.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
|
|
76
|
+
|
|
77
|
+
// Small pause between taps
|
|
78
|
+
tap.addAction(new Pause(finger, Duration.ofMillis(200)));
|
|
79
|
+
|
|
80
|
+
// Second tap
|
|
81
|
+
tap.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
|
|
82
|
+
tap.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
|
|
83
|
+
|
|
84
|
+
// Perform the action
|
|
85
|
+
driver.perform(Collections.singletonList(tap));
|
|
86
|
+
|
|
87
|
+
// Wait to see the result
|
|
88
|
+
Thread.sleep(4000);
|
|
89
|
+
}
|
|
90
|
+
\`\`\`
|
|
91
|
+
|
|
92
|
+
This implementation uses the W3C Actions API which provides more precise control over pointer movements and timing, and is the recommended approach in newer versions of Appium.
|
|
93
|
+
`,
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource for drag and drop gesture documentation
|
|
3
|
+
*/
|
|
4
|
+
export default function dragDropGesture(server) {
|
|
5
|
+
server.addResource({
|
|
6
|
+
uri: 'gesture://drag-drop',
|
|
7
|
+
name: 'Drag and Drop Gesture',
|
|
8
|
+
mimeType: 'text/markdown',
|
|
9
|
+
async load() {
|
|
10
|
+
return {
|
|
11
|
+
text: `
|
|
12
|
+
# Drag and Drop Gesture in Appium
|
|
13
|
+
|
|
14
|
+
The drag and drop gesture simulates dragging an element from one location to another, commonly used in UI testing for moving items between containers.
|
|
15
|
+
|
|
16
|
+
## WebdriverIO Example (v9+)
|
|
17
|
+
\`\`\`javascript
|
|
18
|
+
// Drag and drop element to another element
|
|
19
|
+
const elem = $('#someElem');
|
|
20
|
+
const target = $('#someTarget');
|
|
21
|
+
await elem.dragAndDrop(target);
|
|
22
|
+
|
|
23
|
+
// Drag and drop relative from current position
|
|
24
|
+
await elem.dragAndDrop({ x: 100, y: 200 });
|
|
25
|
+
|
|
26
|
+
// Drag and drop with custom duration
|
|
27
|
+
await elem.dragAndDrop(target, { duration: 2000 }); // 2 seconds
|
|
28
|
+
\`\`\`
|
|
29
|
+
|
|
30
|
+
## WebdriverIO Example (below v9)
|
|
31
|
+
\`\`\`javascript
|
|
32
|
+
// Drag and drop using coordinates with touchAction
|
|
33
|
+
await driver.touchAction([
|
|
34
|
+
{ action: 'press', x: 100, y: 200 },
|
|
35
|
+
{ action: 'wait', ms: 500 },
|
|
36
|
+
{ action: 'moveTo', x: 300, y: 400 },
|
|
37
|
+
{ action: 'release' }
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
// Using the Gestures helper class
|
|
41
|
+
const { x: sourceX, y: sourceY } = await sourceElem.getLocation();
|
|
42
|
+
const { x: targetX, y: targetY } = await targetElem.getLocation();
|
|
43
|
+
|
|
44
|
+
await driver
|
|
45
|
+
.action('pointer')
|
|
46
|
+
.move(sourceX, sourceY)
|
|
47
|
+
.down()
|
|
48
|
+
.pause(500)
|
|
49
|
+
.move({ duration: 1000, x: targetX, y: targetY })
|
|
50
|
+
.up()
|
|
51
|
+
.perform();
|
|
52
|
+
\`\`\`
|
|
53
|
+
|
|
54
|
+
## Appium Java Client Example
|
|
55
|
+
\`\`\`java
|
|
56
|
+
// Implementation from VodQaAdvancedAppium repository
|
|
57
|
+
// Find the element to drag
|
|
58
|
+
WebElement dragMe = new WebDriverWait(driver, Duration.ofSeconds(30))
|
|
59
|
+
.until(elementToBeClickable(AppiumBy.accessibilityId("dragMe")));
|
|
60
|
+
|
|
61
|
+
// Get source location
|
|
62
|
+
Point source = dragMe.getLocation();
|
|
63
|
+
|
|
64
|
+
// Find the drop target
|
|
65
|
+
Point target = driver.findElement(AppiumBy.accessibilityId("dropzone")).getLocation();
|
|
66
|
+
|
|
67
|
+
// Create finger gesture with touch pointer
|
|
68
|
+
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
|
|
69
|
+
Sequence dragNDrop = new Sequence(finger, 1);
|
|
70
|
+
|
|
71
|
+
// Press, move and release
|
|
72
|
+
dragNDrop.addAction(finger.createPointerMove(Duration.ofMillis(0),
|
|
73
|
+
PointerInput.Origin.viewport(), source.x, source.y));
|
|
74
|
+
dragNDrop.addAction(finger.createPointerDown(PointerInput.MouseButton.MIDDLE.asArg()));
|
|
75
|
+
dragNDrop.addAction(finger.createPointerMove(Duration.ofMillis(600),
|
|
76
|
+
PointerInput.Origin.viewport(), target.x, target.y));
|
|
77
|
+
dragNDrop.addAction(finger.createPointerUp(PointerInput.MouseButton.MIDDLE.asArg()));
|
|
78
|
+
|
|
79
|
+
// Perform the action
|
|
80
|
+
driver.perform(Collections.singletonList(dragNDrop));
|
|
81
|
+
|
|
82
|
+
// Verify the drop was successful
|
|
83
|
+
assertEquals(driver.findElements(AppiumBy.accessibilityId("success")).size(), 1);
|
|
84
|
+
\`\`\`
|
|
85
|
+
|
|
86
|
+
This implementation uses the W3C Actions API which provides more precise control over pointer movements and is the recommended approach in newer versions of Appium.
|
|
87
|
+
`,
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic resource for gesture documentation by name
|
|
3
|
+
*/
|
|
4
|
+
export default function gestureByName(server) {
|
|
5
|
+
server.addResourceTemplate({
|
|
6
|
+
uriTemplate: 'gesture://{name}',
|
|
7
|
+
name: 'Gesture by Name',
|
|
8
|
+
mimeType: 'text/markdown',
|
|
9
|
+
arguments: [
|
|
10
|
+
{
|
|
11
|
+
name: 'name',
|
|
12
|
+
description: 'Name of the gesture',
|
|
13
|
+
required: true,
|
|
14
|
+
enum: ['tap', 'swipe', 'scroll', 'pinch-zoom', 'long-press', 'drag-drop', 'double-tap'],
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
async load({ name }) {
|
|
18
|
+
// Map of supported gestures
|
|
19
|
+
const gestures = {
|
|
20
|
+
tap: 'gesture://tap',
|
|
21
|
+
swipe: 'gesture://swipe',
|
|
22
|
+
scroll: 'gesture://scroll',
|
|
23
|
+
'pinch-zoom': 'gesture://pinch-zoom',
|
|
24
|
+
'long-press': 'gesture://long-press',
|
|
25
|
+
'drag-drop': 'gesture://drag-drop',
|
|
26
|
+
'double-tap': 'gesture://double-tap',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if (!gestures[name]) {
|
|
30
|
+
return {
|
|
31
|
+
text: `Gesture "${name}" not found. Available gestures: ${Object.keys(
|
|
32
|
+
gestures
|
|
33
|
+
).join(', ')}`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Redirect to the specific gesture resource
|
|
38
|
+
return {
|
|
39
|
+
text: `Redirecting to ${gestures[name]}...`,
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Export all resources
|
|
2
|
+
import tapGesture from './tap-gesture.js';
|
|
3
|
+
import swipeGesture from './swipe-gesture.js';
|
|
4
|
+
import scrollGesture from './scroll-gesture.js';
|
|
5
|
+
import pinchZoomGesture from './pinch-zoom-gesture.js';
|
|
6
|
+
import longPressGesture from './long-press-gesture.js';
|
|
7
|
+
import dragDropGesture from './drag-drop-gesture.js';
|
|
8
|
+
import doubleTapGesture from './double-tap-gesture.js';
|
|
9
|
+
import gestureByName from './gesture-by-name.js';
|
|
10
|
+
|
|
11
|
+
export default function registerResources(server) {
|
|
12
|
+
// Register all resources
|
|
13
|
+
tapGesture(server);
|
|
14
|
+
swipeGesture(server);
|
|
15
|
+
scrollGesture(server);
|
|
16
|
+
pinchZoomGesture(server);
|
|
17
|
+
longPressGesture(server);
|
|
18
|
+
dragDropGesture(server);
|
|
19
|
+
doubleTapGesture(server);
|
|
20
|
+
gestureByName(server);
|
|
21
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource for long press gesture documentation
|
|
3
|
+
*/
|
|
4
|
+
export default function longPressGesture(server) {
|
|
5
|
+
server.addResource({
|
|
6
|
+
uri: 'gesture://long-press',
|
|
7
|
+
name: 'Long Press Gesture',
|
|
8
|
+
mimeType: 'text/markdown',
|
|
9
|
+
async load() {
|
|
10
|
+
return {
|
|
11
|
+
text: `
|
|
12
|
+
# Long Press Gesture in Appium
|
|
13
|
+
|
|
14
|
+
The long press gesture simulates pressing and holding a finger on a specific element or at specific coordinates.
|
|
15
|
+
|
|
16
|
+
## WebdriverIO Example (v9+)
|
|
17
|
+
\`\`\`javascript
|
|
18
|
+
// Long press on an element
|
|
19
|
+
const contacts = $('~Contacts');
|
|
20
|
+
// Long press with default duration (1500ms)
|
|
21
|
+
await contacts.longPress();
|
|
22
|
+
// Long press with custom duration and offset
|
|
23
|
+
await contacts.longPress({ duration: 5000 }); // 5 seconds
|
|
24
|
+
// Long press with offset from center point of element
|
|
25
|
+
await contacts.longPress({ x: 30, y: 10 });
|
|
26
|
+
\`\`\`
|
|
27
|
+
|
|
28
|
+
## WebdriverIO Example (below v9)
|
|
29
|
+
\`\`\`javascript
|
|
30
|
+
// Long press on an element
|
|
31
|
+
await $('~element-id').touchAction('longPress');
|
|
32
|
+
|
|
33
|
+
// Long press at specific coordinates
|
|
34
|
+
await driver.touchAction([
|
|
35
|
+
{ action: 'longPress', x: 100, y: 200, ms: 2000 },
|
|
36
|
+
{ action: 'release' }
|
|
37
|
+
]);
|
|
38
|
+
\`\`\`
|
|
39
|
+
|
|
40
|
+
## Appium Java Client Example (W3C Actions API)
|
|
41
|
+
\`\`\`java
|
|
42
|
+
// Long press on an element
|
|
43
|
+
WebElement element = driver.findElement(AppiumBy.accessibilityId("elementId"));
|
|
44
|
+
Point source = element.getLocation();
|
|
45
|
+
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
|
|
46
|
+
Sequence sequence = new Sequence(finger, 1);
|
|
47
|
+
|
|
48
|
+
// Move to element, press down, wait, then release
|
|
49
|
+
sequence.addAction(finger.createPointerMove(Duration.ofMillis(0),
|
|
50
|
+
PointerInput.Origin.viewport(), source.x, source.y));
|
|
51
|
+
sequence.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
|
|
52
|
+
// Hold for 2 seconds (2000 milliseconds)
|
|
53
|
+
sequence.addAction(new Pause(finger, Duration.ofMillis(2000)));
|
|
54
|
+
sequence.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
|
|
55
|
+
|
|
56
|
+
// Perform the action
|
|
57
|
+
driver.perform(Collections.singletonList(sequence));
|
|
58
|
+
|
|
59
|
+
// Long press at specific coordinates
|
|
60
|
+
PointerInput finger = new PointerInput(PointerInput.Kind.TOUCH, "finger");
|
|
61
|
+
Sequence sequence = new Sequence(finger, 1);
|
|
62
|
+
|
|
63
|
+
sequence.addAction(finger.createPointerMove(Duration.ofMillis(0),
|
|
64
|
+
PointerInput.Origin.viewport(), 100, 200));
|
|
65
|
+
sequence.addAction(finger.createPointerDown(PointerInput.MouseButton.LEFT.asArg()));
|
|
66
|
+
// Hold for 2 seconds (2000 milliseconds)
|
|
67
|
+
sequence.addAction(new Pause(finger, Duration.ofMillis(2000)));
|
|
68
|
+
sequence.addAction(finger.createPointerUp(PointerInput.MouseButton.LEFT.asArg()));
|
|
69
|
+
|
|
70
|
+
// Perform the action
|
|
71
|
+
driver.perform(Collections.singletonList(sequence));
|
|
72
|
+
\`\`\`
|
|
73
|
+
`,
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|