@aarwitz/tapp 0.17.0-rc.4 → 0.17.0-rc.6
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.
|
@@ -139,6 +139,13 @@ export function isAndroidAppSnapshot(snapshot, appId) {
|
|
|
139
139
|
return ownsActivity || ownsElements;
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
function isSystemOverlayOverApp(snapshot, appId) {
|
|
143
|
+
if (!snapshot || !appId || !String(snapshot.activity || "").startsWith(`${appId}/`)) return false;
|
|
144
|
+
const packages = new Set((snapshot.elements || []).map((element) => element.package).filter(Boolean));
|
|
145
|
+
return packages.size > 0 && !packages.has(appId)
|
|
146
|
+
&& [...packages].every((name) => name === "android" || name.startsWith("com.android.systemui"));
|
|
147
|
+
}
|
|
148
|
+
|
|
142
149
|
export class AndroidDriver {
|
|
143
150
|
constructor({ adbPath = resolveAdbPath(), serial = "", appId = "" } = {}) {
|
|
144
151
|
if (!adbPath) throw new Error("Android testing needs adb. Install Android SDK platform-tools or set ANDROID_SDK_ROOT.");
|
|
@@ -208,12 +215,32 @@ export class AndroidDriver {
|
|
|
208
215
|
return this.waitForOwnedSnapshot();
|
|
209
216
|
}
|
|
210
217
|
|
|
211
|
-
async
|
|
218
|
+
async closeSystemDialogs() {
|
|
219
|
+
// A crash dialog from the previous app can outlive that process and cover a
|
|
220
|
+
// newly launched app. The shell broadcast only closes system-owned surfaces;
|
|
221
|
+
// it does not clear crash history or interact with the app under test.
|
|
222
|
+
await this.adb(["shell", "am", "broadcast", "-a", "android.intent.action.CLOSE_SYSTEM_DIALOGS"]);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async waitForOwnedSnapshot(timeoutMs = 12_000) {
|
|
212
226
|
const deadline = Date.now() + timeoutMs;
|
|
213
227
|
let latest;
|
|
228
|
+
let consecutiveOwned = 0;
|
|
229
|
+
let overlayDismissed = false;
|
|
214
230
|
do {
|
|
215
231
|
latest = await this.snapshot();
|
|
216
|
-
if (isAndroidAppSnapshot(latest, this.appId))
|
|
232
|
+
if (isAndroidAppSnapshot(latest, this.appId)) {
|
|
233
|
+
consecutiveOwned += 1;
|
|
234
|
+
// One mixed dumpsys/UIAutomator sample caused cross-run contamination.
|
|
235
|
+
// Require agreement twice before handing the surface to exploration.
|
|
236
|
+
if (consecutiveOwned >= 2) return latest;
|
|
237
|
+
} else {
|
|
238
|
+
consecutiveOwned = 0;
|
|
239
|
+
if (!overlayDismissed && isSystemOverlayOverApp(latest, this.appId)) {
|
|
240
|
+
overlayDismissed = true;
|
|
241
|
+
await this.closeSystemDialogs();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
217
244
|
if (Date.now() >= deadline) break;
|
|
218
245
|
// Activity and UIAutomator are intentionally required to agree. During app
|
|
219
246
|
// launch they may momentarily describe opposite sides of the transition;
|
package/package.json
CHANGED