@sqaitech/ios 0.5.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/README.md +336 -0
- package/bin/sqai-ios-playground +3 -0
- package/dist/es/bin.mjs +12872 -0
- package/dist/es/bin.mjs.LICENSE.txt +256 -0
- package/dist/es/index.mjs +923 -0
- package/dist/lib/bin.js +13017 -0
- package/dist/lib/bin.js.LICENSE.txt +256 -0
- package/dist/lib/index.js +982 -0
- package/dist/types/bin.d.ts +1 -0
- package/dist/types/index.d.ts +132 -0
- package/package.json +65 -0
- package/static/favicon.ico +0 -0
- package/static/index.html +1 -0
- package/static/static/css/index.60c69390.css +2 -0
- package/static/static/css/index.60c69390.css.map +1 -0
- package/static/static/image/sqai-logo.b7f781cd.png +0 -0
- package/static/static/js/931.dc961e99.js +620 -0
- package/static/static/js/931.dc961e99.js.LICENSE.txt +146 -0
- package/static/static/js/931.dc961e99.js.map +1 -0
- package/static/static/js/async/173.9cf6b074.js +3 -0
- package/static/static/js/async/173.9cf6b074.js.map +1 -0
- package/static/static/js/async/212.e243c338.js +158 -0
- package/static/static/js/async/212.e243c338.js.map +1 -0
- package/static/static/js/async/329.f888b505.js +26 -0
- package/static/static/js/async/329.f888b505.js.map +1 -0
- package/static/static/js/async/364.1821e74b.js +30 -0
- package/static/static/js/async/364.1821e74b.js.map +1 -0
- package/static/static/js/async/544.b73fa603.js +2 -0
- package/static/static/js/async/544.b73fa603.js.map +1 -0
- package/static/static/js/async/582.5dccae2d.js +21 -0
- package/static/static/js/async/582.5dccae2d.js.map +1 -0
- package/static/static/js/async/624.45ee2b2c.js +3 -0
- package/static/static/js/async/624.45ee2b2c.js.map +1 -0
- package/static/static/js/async/644.6bdc4065.js +1 -0
- package/static/static/js/async/659.9afd03db.js +21 -0
- package/static/static/js/async/659.9afd03db.js.map +1 -0
- package/static/static/js/async/702.60261735.js +231 -0
- package/static/static/js/async/702.60261735.js.map +1 -0
- package/static/static/js/async/920.7d9a9aa8.js +2 -0
- package/static/static/js/async/920.7d9a9aa8.js.map +1 -0
- package/static/static/js/async/983.8b91303f.js +1 -0
- package/static/static/js/index.0c5d4f3b.js +10 -0
- package/static/static/js/index.0c5d4f3b.js.LICENSE.txt +7 -0
- package/static/static/js/index.0c5d4f3b.js.map +1 -0
- package/static/static/js/index.3890f2de.js +10 -0
- package/static/static/js/index.3890f2de.js.LICENSE.txt +7 -0
- package/static/static/js/index.3890f2de.js.map +1 -0
- package/static/static/js/index.39b0d1ea.js +10 -0
- package/static/static/js/index.39b0d1ea.js.LICENSE.txt +7 -0
- package/static/static/js/index.39b0d1ea.js.map +1 -0
- package/static/static/js/index.3f24d218.js +10 -0
- package/static/static/js/index.3f24d218.js.LICENSE.txt +7 -0
- package/static/static/js/index.3f24d218.js.map +1 -0
- package/static/static/js/index.5cccbdaf.js +10 -0
- package/static/static/js/index.5cccbdaf.js.LICENSE.txt +7 -0
- package/static/static/js/index.5cccbdaf.js.map +1 -0
- package/static/static/js/index.8a10896b.js +10 -0
- package/static/static/js/index.8a10896b.js.LICENSE.txt +7 -0
- package/static/static/js/index.8a10896b.js.map +1 -0
- package/static/static/js/index.afc8ef37.js +10 -0
- package/static/static/js/index.afc8ef37.js.LICENSE.txt +7 -0
- package/static/static/js/index.afc8ef37.js.map +1 -0
- package/static/static/js/index.b8a17a87.js +10 -0
- package/static/static/js/index.b8a17a87.js.LICENSE.txt +7 -0
- package/static/static/js/index.b8a17a87.js.map +1 -0
- package/static/static/js/index.d0dcab60.js +10 -0
- package/static/static/js/index.d0dcab60.js.LICENSE.txt +7 -0
- package/static/static/js/index.d0dcab60.js.map +1 -0
- package/static/static/js/index.f21bb1df.js +10 -0
- package/static/static/js/index.f21bb1df.js.LICENSE.txt +7 -0
- package/static/static/js/index.f21bb1df.js.map +1 -0
- package/static/static/js/lib-react.f566a9ed.js +3 -0
- package/static/static/js/lib-react.f566a9ed.js.LICENSE.txt +39 -0
- package/static/static/js/lib-react.f566a9ed.js.map +1 -0
- package/static/static/svg/server-offline-foreground.3113df3c.svg +36 -0
- package/static/static/wasm/9e906fbf55e08f98.module.wasm +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# @SQAI/ios
|
|
2
|
+
|
|
3
|
+
iOS automation library for SQAI, providing AI-powered testing and automation capabilities for iOS simulators and devices.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎯 **iOS Simulator Support** - Full automation support for iOS simulators
|
|
8
|
+
- 🤖 **AI-Powered Actions** - Intelligent element detection and interaction
|
|
9
|
+
- 📱 **Native iOS Actions** - Home button, app switcher, and iOS-specific gestures
|
|
10
|
+
- 🔧 **Simple API** - Easy-to-use interface similar to @SQAI/android
|
|
11
|
+
- 📸 **Screenshot Capture** - Built-in screenshot functionality
|
|
12
|
+
- ⌨️ **Text Input** - Support for text input including non-ASCII characters
|
|
13
|
+
- 🎮 **Gesture Support** - Tap, swipe, long press, and custom gestures
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
- **macOS** (required for iOS development)
|
|
18
|
+
- **Xcode** and Xcode Command Line Tools
|
|
19
|
+
- **iOS Simulator** or physical iOS device
|
|
20
|
+
- **WebDriverAgent** (required for automation)
|
|
21
|
+
|
|
22
|
+
### Environment Setup
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Install Xcode Command Line Tools
|
|
26
|
+
xcode-select --install
|
|
27
|
+
|
|
28
|
+
# Verify simctl is available
|
|
29
|
+
xcrun simctl list devices
|
|
30
|
+
|
|
31
|
+
# Install WebDriverAgent dependency
|
|
32
|
+
npm install appium-webdriveragent
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### WebDriverAgent Setup
|
|
36
|
+
|
|
37
|
+
SQAI iOS uses WebDriverAgent for device automation. You need to prepare WebDriverAgent before using the library:
|
|
38
|
+
|
|
39
|
+
#### For iOS Simulators
|
|
40
|
+
|
|
41
|
+
1. **Install WebDriverAgent dependency:**
|
|
42
|
+
```bash
|
|
43
|
+
npm install appium-webdriveragent
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
2. **Build and start WebDriverAgent:**
|
|
47
|
+
```bash
|
|
48
|
+
# Navigate to WebDriverAgent project
|
|
49
|
+
cd node_modules/appium-webdriveragent
|
|
50
|
+
|
|
51
|
+
# Build and run for simulator
|
|
52
|
+
xcodebuild -project WebDriverAgent.xcodeproj \
|
|
53
|
+
-scheme WebDriverAgentRunner \
|
|
54
|
+
-destination 'platform=iOS Simulator,name=iPhone 15' \
|
|
55
|
+
test
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### For Physical iOS Devices
|
|
59
|
+
|
|
60
|
+
1. **Configure Development Team:**
|
|
61
|
+
- Open `node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj` in Xcode
|
|
62
|
+
- Select your Development Team for both `WebDriverAgentLib` and `WebDriverAgentRunner` targets
|
|
63
|
+
- Ensure proper code signing is configured
|
|
64
|
+
|
|
65
|
+
2. **Build and deploy to device:**
|
|
66
|
+
```bash
|
|
67
|
+
# Replace DEVICE_UDID with your device's UDID
|
|
68
|
+
xcodebuild -project WebDriverAgent.xcodeproj \
|
|
69
|
+
-scheme WebDriverAgentRunner \
|
|
70
|
+
-destination 'id=YOUR_DEVICE_UDID' \
|
|
71
|
+
test
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
3. **Trust Developer Certificate:**
|
|
75
|
+
- On your iOS device, go to Settings > General > VPN & Device Management
|
|
76
|
+
- Trust your developer certificate
|
|
77
|
+
|
|
78
|
+
4. **Set up port forwarding (for real devices):**
|
|
79
|
+
```bash
|
|
80
|
+
# Install iproxy (if needed)
|
|
81
|
+
brew install libimobiledevice
|
|
82
|
+
|
|
83
|
+
# Forward local port 8100 to device port 8100
|
|
84
|
+
iproxy -u YOUR_DEVICE_ID 8100:8100
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### Alternative Setup Methods
|
|
88
|
+
|
|
89
|
+
For more advanced setup options and troubleshooting, refer to the official WebDriverAgent documentation:
|
|
90
|
+
**📖 [WebDriverAgent Setup Guide](https://appium.github.io/appium-xcuitest-driver/4.25/wda-custom-server/)**
|
|
91
|
+
|
|
92
|
+
> **⚠️ Important:** WebDriverAgent must be running on port 8100 (default) before using SQAI iOS. If WebDriverAgent is not detected, you'll receive setup instructions.
|
|
93
|
+
|
|
94
|
+
## Installation
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npm install @SQAI/ios
|
|
98
|
+
# or
|
|
99
|
+
pnpm add @SQAI/ios
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Quick Start
|
|
103
|
+
|
|
104
|
+
### Basic Usage (Recommended)
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { agentFromWebDriverAgent } from '@SQAI/ios';
|
|
108
|
+
|
|
109
|
+
// Connect to WebDriverAgent (auto-detects device)
|
|
110
|
+
const agent = await agentFromWebDriverAgent();
|
|
111
|
+
|
|
112
|
+
// Launch an app
|
|
113
|
+
await agent.launch('com.apple.MobileSafari');
|
|
114
|
+
|
|
115
|
+
// Perform AI-powered actions
|
|
116
|
+
await agent.aiAction('tap on the address bar');
|
|
117
|
+
await agent.aiAction('type "https://example.com"');
|
|
118
|
+
await agent.aiAction('tap the go button');
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Using Custom WebDriverAgent Configuration
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
import { agentFromWebDriverAgent } from '@SQAI/ios';
|
|
125
|
+
|
|
126
|
+
// Connect to WebDriverAgent on custom host/port
|
|
127
|
+
const agent = await agentFromWebDriverAgent({
|
|
128
|
+
wdaHost: 'localhost',
|
|
129
|
+
wdaPort: 8100, // Custom port
|
|
130
|
+
aiActionContext: 'If any popup appears, click agree',
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Launch app and interact
|
|
134
|
+
await agent.launch('com.yourapp.bundleid');
|
|
135
|
+
await agent.aiAction('tap the login button');
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## API Reference
|
|
139
|
+
|
|
140
|
+
### IOSDevice
|
|
141
|
+
|
|
142
|
+
Core device automation class implementing the AbstractInterface.
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { IOSDevice } from '@SQAI/ios';
|
|
146
|
+
|
|
147
|
+
// Create device (deviceId is auto-detected from WebDriverAgent)
|
|
148
|
+
const device = new IOSDevice({
|
|
149
|
+
wdaHost: 'localhost',
|
|
150
|
+
wdaPort: 8100,
|
|
151
|
+
});
|
|
152
|
+
await device.connect();
|
|
153
|
+
|
|
154
|
+
// Basic interactions
|
|
155
|
+
await device.tap(100, 200);
|
|
156
|
+
await device.swipe(100, 200, 300, 400);
|
|
157
|
+
await device.typeText('Hello World');
|
|
158
|
+
await device.pressKey('Enter');
|
|
159
|
+
|
|
160
|
+
// iOS-specific actions
|
|
161
|
+
await device.home();
|
|
162
|
+
await device.appSwitcher();
|
|
163
|
+
await device.longPress(150, 300, 1000);
|
|
164
|
+
|
|
165
|
+
// Screenshots
|
|
166
|
+
const screenshot = await device.screenshotBase64();
|
|
167
|
+
|
|
168
|
+
// Cleanup
|
|
169
|
+
await device.destroy();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### IOSAgent
|
|
173
|
+
|
|
174
|
+
High-level agent for AI-powered automation.
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { IOSAgent, agentFromWebDriverAgent } from '@SQAI/ios';
|
|
178
|
+
|
|
179
|
+
// Recommended approach
|
|
180
|
+
const agent = await agentFromWebDriverAgent();
|
|
181
|
+
|
|
182
|
+
// AI actions
|
|
183
|
+
await agent.aiAction('tap the settings icon');
|
|
184
|
+
await agent.aiQuery('what is the current battery level?');
|
|
185
|
+
await agent.aiWaitFor('the page is loaded');
|
|
186
|
+
|
|
187
|
+
// App management
|
|
188
|
+
await agent.launch('com.apple.Preferences');
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Utility Functions
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import {
|
|
195
|
+
checkIOSEnvironment,
|
|
196
|
+
ensureSimulatorBooted,
|
|
197
|
+
// Note: getConnectedDevices and getDefaultDevice are deprecated
|
|
198
|
+
// Use agentFromWebDriverAgent() instead
|
|
199
|
+
} from '@SQAI/ios';
|
|
200
|
+
|
|
201
|
+
// Environment check
|
|
202
|
+
const envStatus = await checkIOSEnvironment();
|
|
203
|
+
console.log('iOS environment available:', envStatus.available);
|
|
204
|
+
|
|
205
|
+
// Simulator management (if needed)
|
|
206
|
+
await ensureSimulatorBooted('simulator-udid');
|
|
207
|
+
|
|
208
|
+
// Simulator management
|
|
209
|
+
await ensureSimulatorBooted('device-udid');
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Configuration
|
|
213
|
+
|
|
214
|
+
Set environment variables for default behavior:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Default device UDID
|
|
218
|
+
export SQAI_IOS_DEVICE_UDID=your-device-udid
|
|
219
|
+
|
|
220
|
+
# Default simulator UDID
|
|
221
|
+
export SQAI_IOS_SIMULATOR_UDID=your-simulator-udid
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Supported iOS Actions
|
|
225
|
+
|
|
226
|
+
### Basic Gestures
|
|
227
|
+
- `tap(x, y)` - Single tap at coordinates
|
|
228
|
+
- `doubleTap(x, y)` - Double tap at coordinates
|
|
229
|
+
- `longPress(x, y, duration)` - Long press with duration
|
|
230
|
+
- `swipe(fromX, fromY, toX, toY)` - Swipe gesture
|
|
231
|
+
|
|
232
|
+
### Text Input
|
|
233
|
+
- `typeText(text)` - Type text using iOS keyboard
|
|
234
|
+
- `pressKey(key)` - Press specific keys (Enter, Backspace, etc.)
|
|
235
|
+
- `clearInput(element)` - Clear input field
|
|
236
|
+
|
|
237
|
+
### Scrolling
|
|
238
|
+
- `scrollUp/Down/Left/Right(distance?, startPoint?)` - Directional scrolling
|
|
239
|
+
- `scrollUntilTop/Bottom/Left/Right(startPoint?)` - Scroll to extremes
|
|
240
|
+
|
|
241
|
+
### iOS System Actions
|
|
242
|
+
- `home()` - Press home button
|
|
243
|
+
- `appSwitcher()` - Open app switcher
|
|
244
|
+
- `hideKeyboard()` - Dismiss keyboard
|
|
245
|
+
|
|
246
|
+
### AI-Powered Actions
|
|
247
|
+
- `aiAction(instruction)` - Perform action based on natural language
|
|
248
|
+
- `aiQuery(question)` - Query UI state with natural language
|
|
249
|
+
- `aiWaitFor(condition)` - Wait for condition to be met
|
|
250
|
+
|
|
251
|
+
## Device Requirements
|
|
252
|
+
|
|
253
|
+
### iOS Simulators
|
|
254
|
+
- Managed through Xcode
|
|
255
|
+
- No additional setup required
|
|
256
|
+
- Supports all iOS versions available in Xcode
|
|
257
|
+
|
|
258
|
+
### Physical iOS Devices
|
|
259
|
+
- Requires iOS 9.0 or later
|
|
260
|
+
- Device must be in Developer Mode
|
|
261
|
+
- Requires valid provisioning profile for your apps
|
|
262
|
+
|
|
263
|
+
## Examples
|
|
264
|
+
|
|
265
|
+
### Complete Test Example
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import { describe, it } from 'vitest';
|
|
269
|
+
import { agentFromWebDriverAgent } from '@SQAI/ios';
|
|
270
|
+
|
|
271
|
+
describe('iOS App Test', () => {
|
|
272
|
+
it('should login to app', async () => {
|
|
273
|
+
// WebDriverAgent auto-detects the connected device
|
|
274
|
+
const agent = await agentFromWebDriverAgent();
|
|
275
|
+
|
|
276
|
+
// Launch your app
|
|
277
|
+
await agent.launch('com.yourcompany.yourapp');
|
|
278
|
+
|
|
279
|
+
// AI-powered login flow
|
|
280
|
+
await agent.aiAction('tap on email field');
|
|
281
|
+
await agent.aiAction('type "user@example.com"');
|
|
282
|
+
await agent.aiAction('tap on password field');
|
|
283
|
+
await agent.aiAction('type "password123"');
|
|
284
|
+
await agent.aiAction('tap the login button');
|
|
285
|
+
|
|
286
|
+
// Verify successful login
|
|
287
|
+
await agent.aiWaitFor('dashboard is visible');
|
|
288
|
+
|
|
289
|
+
const isLoggedIn = await agent.aiQuery('is the user logged in?');
|
|
290
|
+
expect(isLoggedIn).toBe(true);
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Troubleshooting
|
|
296
|
+
|
|
297
|
+
### Common Issues
|
|
298
|
+
|
|
299
|
+
1. **"No iOS devices available"**
|
|
300
|
+
- Ensure Xcode is installed
|
|
301
|
+
- Check `xcrun simctl list devices` shows available simulators
|
|
302
|
+
- Try booting a simulator manually in Xcode
|
|
303
|
+
|
|
304
|
+
2. **"Command failed: xcrun simctl"**
|
|
305
|
+
- Verify Xcode Command Line Tools are installed
|
|
306
|
+
- Run `xcode-select --install` if needed
|
|
307
|
+
- Check `which xcrun` returns a valid path
|
|
308
|
+
|
|
309
|
+
3. **Simulator not responding**
|
|
310
|
+
- Restart the simulator
|
|
311
|
+
- Try `xcrun simctl shutdown all && xcrun simctl boot <udid>`
|
|
312
|
+
|
|
313
|
+
4. **App launch fails**
|
|
314
|
+
- Verify the bundle ID is correct
|
|
315
|
+
- Ensure the app is installed on the simulator
|
|
316
|
+
- Check app permissions and entitlements
|
|
317
|
+
|
|
318
|
+
### Debug Mode
|
|
319
|
+
|
|
320
|
+
Enable debug logging:
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
process.env.DEBUG = 'ios:*';
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Contributing
|
|
327
|
+
|
|
328
|
+
1. Fork the repository
|
|
329
|
+
2. Create your feature branch
|
|
330
|
+
3. Add tests for new functionality
|
|
331
|
+
4. Ensure all tests pass
|
|
332
|
+
5. Submit a pull request
|
|
333
|
+
|
|
334
|
+
## License
|
|
335
|
+
|
|
336
|
+
MIT License - see LICENSE file for details.
|