also looking at this
test(mobile-e2e): prove Android reports approximate location as granted
#214
5 files
+85
-5
| @@ -89,6 +89,7 @@ export const REQUIRED_CASES: Record<MobilePlatform, string[]> = { | ||
| 89 | 89 | 'push.disabled.rejects', |
| 90 | 90 | 'share.empty.rejects', |
| 91 | 91 | 'share.dismissed.resolvesFalse', |
| 92 | 'permissions.location.granted', | |
| 92 | 93 | ], |
| 93 | 94 | } |
| 94 | 95 | |
| @@ -354,6 +355,23 @@ export function shareMenuInFront(dumpsysWindow: string): boolean { | ||
| 354 | 355 | .some(line => /mCurrentFocus=/.test(line) && /ChooserActivity/.test(line)) |
| 355 | 356 | } |
| 356 | 357 | |
| 358 | /** | |
| 359 | * Whether `dumpsys package` says a runtime permission is granted, or | |
| 360 | * `undefined` when the output does not mention it at all. | |
| 361 | * | |
| 362 | * Three answers rather than two, because "not mentioned" usually means the | |
| 363 | * manifest never declared the permission, and reading that as "not granted" | |
| 364 | * would hide the cause. | |
| 365 | */ | |
| 366 | export function runtimePermissionGranted(dumpsysPackage: string, permission: string): boolean | undefined { | |
| 367 | const escaped = permission.replaceAll('.', '\\.') | |
| 368 | // Whitespace or line start before the name, not a word boundary, which sits | |
| 369 | // after every dot, so `permission.CAMERA` would match inside | |
| 370 | // `android.permission.CAMERA`. | |
| 371 | const match = dumpsysPackage.match(new RegExp(`(?:^|\\s)${escaped}: granted=(true|false)`, 'm')) | |
| 372 | return match ? match[1] === 'true' : undefined | |
| 373 | } | |
| 374 | ||
| 357 | 375 | /** |
| 358 | 376 | * The actions the Zig dispatcher saw, by name. |
| 359 | 377 | * |