@appium/coresim 1.11.1 → 1.13.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/CHANGELOG.md +14 -0
- package/README.md +6 -1
- package/lib/src/commands/jpeg-stream.d.ts +2 -0
- package/lib/src/commands/jpeg-stream.d.ts.map +1 -1
- package/lib/src/commands/jpeg-stream.js +6 -2
- package/lib/src/commands/jpeg-stream.js.map +1 -1
- package/lib/src/commands/permissions.d.ts +15 -7
- package/lib/src/commands/permissions.d.ts.map +1 -1
- package/lib/src/commands/permissions.js +299 -5
- package/lib/src/commands/permissions.js.map +1 -1
- package/lib/src/commands/screenshot.d.ts +3 -3
- package/lib/src/commands/screenshot.d.ts.map +1 -1
- package/lib/src/commands/screenshot.js +10 -5
- package/lib/src/commands/screenshot.js.map +1 -1
- package/lib/src/commands/video-recording.d.ts +2 -0
- package/lib/src/commands/video-recording.d.ts.map +1 -1
- package/lib/src/commands/video-recording.js +13 -6
- package/lib/src/commands/video-recording.js.map +1 -1
- package/lib/src/commands/video-stream.d.ts +2 -0
- package/lib/src/commands/video-stream.d.ts.map +1 -1
- package/lib/src/commands/video-stream.js +6 -2
- package/lib/src/commands/video-stream.js.map +1 -1
- package/lib/src/index.d.ts +1 -1
- package/lib/src/index.d.ts.map +1 -1
- package/lib/src/index.js.map +1 -1
- package/lib/src/types.d.ts +25 -31
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/utils/display.d.ts +24 -0
- package/lib/src/utils/display.d.ts.map +1 -0
- package/lib/src/utils/display.js +55 -0
- package/lib/src/utils/display.js.map +1 -0
- package/lib/src/utils/index.d.ts +1 -0
- package/lib/src/utils/index.d.ts.map +1 -1
- package/lib/src/utils/index.js +1 -0
- package/lib/src/utils/index.js.map +1 -1
- package/package.json +3 -4
- package/prebuilds/darwin-arm64/@appium+coresim.node +0 -0
- package/src/commands/jpeg-stream.ts +6 -2
- package/src/commands/permissions.ts +324 -10
- package/src/commands/screenshot.ts +10 -5
- package/src/commands/video-recording.ts +10 -5
- package/src/commands/video-stream.ts +6 -2
- package/src/coresim.mm +7 -0
- package/src/index.ts +2 -0
- package/src/native/sim_screenshot.h +12 -7
- package/src/native/sim_screenshot.mm +18 -2
- package/src/types.ts +27 -30
- package/src/utils/display.ts +67 -0
- package/src/utils/index.ts +1 -0
package/src/types.ts
CHANGED
|
@@ -87,9 +87,10 @@ export type SimPermissionStatus = 'unset' | 'denied' | 'granted' | 'limited';
|
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
89
|
* A privacy permission grantable via `NativeSimctl.grantPermission`/`revokePermission`/
|
|
90
|
-
* `resetPermission`. Each is backed by a row in the simulator's own TCC
|
|
91
|
-
* `location` isn't included since CoreLocation simulation has its own
|
|
92
|
-
* row (see CLAUDE.md).
|
|
90
|
+
* `resetPermission`. Each except `notifications` is backed by a row in the simulator's own TCC
|
|
91
|
+
* (privacy) database — `location` isn't included since CoreLocation simulation has its own
|
|
92
|
+
* subsystem, not a plain TCC row (see CLAUDE.md). `notifications` is SpringBoard's own setting:
|
|
93
|
+
* changing it restarts SpringBoard, and its status can't be read back via `getPermission`.
|
|
93
94
|
*/
|
|
94
95
|
export type SimPermissionService =
|
|
95
96
|
| 'calendar'
|
|
@@ -101,6 +102,7 @@ export type SimPermissionService =
|
|
|
101
102
|
| 'medialibrary'
|
|
102
103
|
| 'microphone'
|
|
103
104
|
| 'motion'
|
|
105
|
+
| 'notifications'
|
|
104
106
|
| 'photos'
|
|
105
107
|
| 'reminders'
|
|
106
108
|
| 'siri'
|
|
@@ -111,23 +113,32 @@ export type SimPermissionService =
|
|
|
111
113
|
* A device's renderable display, as returned by `NativeSimctl.getDisplays()`.
|
|
112
114
|
*/
|
|
113
115
|
export interface SimDisplayInfo {
|
|
114
|
-
/** Port UUID identifying this display — pass as
|
|
116
|
+
/** Port UUID identifying this display — pass as a capture API’s `displayId` option to target it. */
|
|
115
117
|
id: string;
|
|
116
|
-
/**
|
|
118
|
+
/** Guest screen ID (`SimScreenProperties.screenID`), when available. Matches XCTest displayID. */
|
|
119
|
+
screenId?: number;
|
|
120
|
+
/** Raw `SimDisplayDescriptorState.displayClass` — 0 includes both built-in displays on Duo. */
|
|
117
121
|
displayClass: number;
|
|
118
|
-
/** Whether
|
|
122
|
+
/** Whether `displayClass === 0`. Multiple integrated displays may have this value. */
|
|
119
123
|
isMain: boolean;
|
|
120
124
|
}
|
|
121
125
|
|
|
126
|
+
/** Port UUID string or unsigned 32-bit guest screen ID (XCTest/WDA displayID). */
|
|
127
|
+
export type DisplayId = string | number;
|
|
128
|
+
|
|
129
|
+
/** Display selection shared by screenshot, recording, and streaming APIs. */
|
|
130
|
+
export interface DisplayOptions {
|
|
131
|
+
/**
|
|
132
|
+
* Port UUID from `getDisplays()`, or an unsigned 32-bit guest screen ID (XCTest/WDA displayID).
|
|
133
|
+
* See [display selection helpers](./utils/display.ts) for validation and resolution semantics.
|
|
134
|
+
*/
|
|
135
|
+
displayId?: DisplayId;
|
|
136
|
+
}
|
|
137
|
+
|
|
122
138
|
/** Options for `NativeSimctl.getScreenshot`. */
|
|
123
|
-
export interface ScreenshotOptions {
|
|
139
|
+
export interface ScreenshotOptions extends DisplayOptions {
|
|
124
140
|
/** Image encoding — defaults to `'png'`. */
|
|
125
141
|
format?: 'png' | 'jpeg';
|
|
126
|
-
/**
|
|
127
|
-
* Which display to capture, by `id` from `getDisplays()`. Defaults to the primary display
|
|
128
|
-
* (falling back to the first renderable display if none is primary, e.g. tvOS).
|
|
129
|
-
*/
|
|
130
|
-
displayId?: string;
|
|
131
142
|
/**
|
|
132
143
|
* JPEG quality as a percentage (0 = smallest/most compressed, 100 = largest/least compressed).
|
|
133
144
|
* Only meaningful with `format: 'jpeg'` — ignored for `'png'`, which is always lossless.
|
|
@@ -137,12 +148,7 @@ export interface ScreenshotOptions {
|
|
|
137
148
|
}
|
|
138
149
|
|
|
139
150
|
/** Options for `NativeSimctl.startVideoRecording`. */
|
|
140
|
-
export interface VideoRecordingOptions {
|
|
141
|
-
/**
|
|
142
|
-
* Which display to record, by `id` from `getDisplays()`. Defaults to the primary display
|
|
143
|
-
* (falling back to the first renderable display if none is primary, e.g. tvOS).
|
|
144
|
-
*/
|
|
145
|
-
displayId?: string;
|
|
151
|
+
export interface VideoRecordingOptions extends DisplayOptions {
|
|
146
152
|
/** Video codec — `'h264'` (default) or `'hevc'`. */
|
|
147
153
|
codec?: 'h264' | 'hevc';
|
|
148
154
|
/**
|
|
@@ -189,12 +195,7 @@ export interface StopVideoRecordingOptions {
|
|
|
189
195
|
}
|
|
190
196
|
|
|
191
197
|
/** Options for `NativeSimctl.startVideoStream`. */
|
|
192
|
-
export interface VideoStreamOptions {
|
|
193
|
-
/**
|
|
194
|
-
* Which display to stream, by `id` from `getDisplays()`. Defaults to the primary display
|
|
195
|
-
* (falling back to the first renderable display if none is primary, e.g. tvOS).
|
|
196
|
-
*/
|
|
197
|
-
displayId?: string;
|
|
198
|
+
export interface VideoStreamOptions extends DisplayOptions {
|
|
198
199
|
/** Video codec — `'h264'` (default) or `'hevc'`. */
|
|
199
200
|
codec?: 'h264' | 'hevc';
|
|
200
201
|
/**
|
|
@@ -213,12 +214,7 @@ export interface VideoStreamOptions {
|
|
|
213
214
|
}
|
|
214
215
|
|
|
215
216
|
/** Options for `NativeSimctl.startJpegStream`. */
|
|
216
|
-
export interface JpegStreamOptions {
|
|
217
|
-
/**
|
|
218
|
-
* Which display to stream, by `id` from `getDisplays()`. Defaults to the primary display
|
|
219
|
-
* (falling back to the first renderable display if none is primary, e.g. tvOS).
|
|
220
|
-
*/
|
|
221
|
-
displayId?: string;
|
|
217
|
+
export interface JpegStreamOptions extends DisplayOptions {
|
|
222
218
|
/**
|
|
223
219
|
* Max frames/sec to poll the framebuffer at — an unchanged frame is never re-encoded, so this
|
|
224
220
|
* is an upper bound, not a guarantee. Must be >= 1. Defaults to 60.
|
|
@@ -430,6 +426,7 @@ export interface NativeDeviceHandle {
|
|
|
430
426
|
deviceTypeIdentifier(): string;
|
|
431
427
|
runtimeIdentifier(): string;
|
|
432
428
|
runtimeRootPath(): string;
|
|
429
|
+
dataPath(): string;
|
|
433
430
|
boot(options?: Record<string, unknown>): Promise<void>;
|
|
434
431
|
getBootStatus(): Promise<SimBootInfo | null>;
|
|
435
432
|
shutdown(): Promise<void>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type {DisplayId, NativeDeviceHandle, SimDisplayInfo} from '../types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Validates a capture API's display selection without querying the device.
|
|
5
|
+
* Strings pass through without UUID syntax or port-existence checks.
|
|
6
|
+
*
|
|
7
|
+
* @param displayId — port UUID string, unsigned 32-bit guest screen ID, or `undefined` for default selection
|
|
8
|
+
* @throws {TypeError} if the value is neither a string, a number, nor `undefined`
|
|
9
|
+
* @throws {RangeError} if a numeric value is not an unsigned 32-bit integer
|
|
10
|
+
*/
|
|
11
|
+
export function validateDisplayId(displayId: unknown): void {
|
|
12
|
+
if (displayId !== undefined && typeof displayId !== 'string' && typeof displayId !== 'number') {
|
|
13
|
+
throw new TypeError('displayId must be a port UUID string or a numeric guest screen ID');
|
|
14
|
+
}
|
|
15
|
+
if (typeof displayId === 'number' && (!Number.isInteger(displayId) || displayId < 0 || displayId > 0xffffffff)) {
|
|
16
|
+
throw new RangeError('A numeric displayId must be an unsigned 32-bit integer');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Resolves a validated display selection to the port UUID expected by native capture APIs.
|
|
22
|
+
* UUID strings pass through without enumeration; numeric IDs are matched against a fresh list
|
|
23
|
+
* of guest screen IDs (XCTest/WDA displayID) on each call. An omitted ID selects the unique `isMain` (class-0) port.
|
|
24
|
+
* If no class-0 port exists, native capture falls back to the first renderable display.
|
|
25
|
+
* Call once at recording/stream startup, or on each screenshot capture.
|
|
26
|
+
*
|
|
27
|
+
* @param device — native handle for the device whose display ports are queried
|
|
28
|
+
* @param displayId — selection already checked by {@link validateDisplayId}
|
|
29
|
+
* @returns the selected port UUID, or `undefined` to retain native fallback when no default port exists
|
|
30
|
+
* @throws {Error} if a numeric ID has no unique match with a nonempty UUID, or multiple default ports exist
|
|
31
|
+
*/
|
|
32
|
+
export async function resolveDisplayPortId(
|
|
33
|
+
device: NativeDeviceHandle,
|
|
34
|
+
displayId: DisplayId | undefined,
|
|
35
|
+
): Promise<string | undefined> {
|
|
36
|
+
if (typeof displayId === 'string') {
|
|
37
|
+
return displayId;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const displays = await device.getDisplays();
|
|
41
|
+
if (typeof displayId === 'number') {
|
|
42
|
+
const matches = displays.filter(({screenId}) => screenId === displayId);
|
|
43
|
+
if (matches.length !== 1 || !matches[0].id) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`Cannot uniquely resolve guest screen ID ${displayId} to a display port. ${availableDisplayIdsHint(displays)}`,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return matches[0].id;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Both integrated Duo displays have class 0. Never pick one by port order.
|
|
52
|
+
const defaults = displays.filter(({isMain}) => isMain);
|
|
53
|
+
if (defaults.length > 1) {
|
|
54
|
+
throw new Error(
|
|
55
|
+
`Multiple default display ports are available; specify displayId. ${availableDisplayIdsHint(displays)}`,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return defaults[0]?.id;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Formats the already-fetched screen ID/port UUID pairs for display-selection errors. */
|
|
62
|
+
function availableDisplayIdsHint(displays: SimDisplayInfo[]): string {
|
|
63
|
+
if (displays.length === 0) {
|
|
64
|
+
return 'Available display IDs: none';
|
|
65
|
+
}
|
|
66
|
+
return `Available display IDs: ${JSON.stringify(displays.map(({id, screenId}) => ({screenId, id})))}`;
|
|
67
|
+
}
|
package/src/utils/index.ts
CHANGED