appium-cdp-driver 1.0.7 → 1.0.8
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/build/scripts/brave.js +116 -0
- package/build/scripts/browserReady.js +302 -0
- package/build/scripts/duckduckgo.js +122 -0
- package/build/scripts/edge.js +221 -0
- package/build/scripts/opera.js +170 -0
- package/build/scripts/samsung.js +152 -0
- package/build/src/adb.js +163 -0
- package/build/src/cdp.js +22 -0
- package/build/src/commands/cookies.js +63 -0
- package/build/src/commands/createSession.js +2 -0
- package/build/src/commands/document.js +24 -0
- package/build/src/commands/element.js +85 -0
- package/build/src/commands/find.js +78 -0
- package/build/src/commands/index.js +16 -0
- package/build/src/commands/navigation.js +34 -0
- package/build/src/commands/screencapture.js +31 -0
- package/build/src/commands/url.js +34 -0
- package/build/src/driver.js +131 -0
- package/build/src/index.js +51 -0
- package/build/src/logger.js +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
const appium_uiautomator2_driver_1 = require("appium-uiautomator2-driver");
|
|
17
|
+
const appium_adb_1 = require("appium-adb");
|
|
18
|
+
const adb_js_1 = require("../src/adb.js");
|
|
19
|
+
const logger_js_1 = __importDefault(require("../src/logger.js"));
|
|
20
|
+
const asyncbox_1 = require("asyncbox");
|
|
21
|
+
const browserReady_js_1 = require("./browserReady.js");
|
|
22
|
+
const START_APP_WAIT_DURATION = 60000;
|
|
23
|
+
const edge = {
|
|
24
|
+
pkg: 'com.microsoft.emmx',
|
|
25
|
+
activity: 'com.microsoft.ruby.Main',
|
|
26
|
+
};
|
|
27
|
+
const common = {
|
|
28
|
+
waitDuration: START_APP_WAIT_DURATION,
|
|
29
|
+
optionalIntentArguments: '-d www.appium.io',
|
|
30
|
+
};
|
|
31
|
+
function skipWelcomeEdge() {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
const adbPort = (0, adb_js_1.resolveAdbPort)();
|
|
34
|
+
const adb = yield appium_adb_1.ADB.createADB({ adbPort });
|
|
35
|
+
yield adb.adbExec(['shell', 'pm', 'clear', edge.pkg]);
|
|
36
|
+
// Optional: suppress Chromium's first-run experience. Off by default because
|
|
37
|
+
// /data/local/tmp/chrome-command-line is shared with Chrome and chromedriver,
|
|
38
|
+
// which writes its own chromeOptions.args there — clobbering it would change
|
|
39
|
+
// an unrelated Chrome session on the same device. Set CDP_SUPPRESS_FIRST_RUN=1
|
|
40
|
+
// to opt in; without it the readiness pass dismisses onboarding instead.
|
|
41
|
+
if (process.env.CDP_SUPPRESS_FIRST_RUN === '1') {
|
|
42
|
+
yield adb.adbExec([
|
|
43
|
+
'shell',
|
|
44
|
+
"echo '_ --disable-fre --no-first-run' > /data/local/tmp/chrome-command-line",
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
const driver = new appium_uiautomator2_driver_1.AndroidUiautomator2Driver();
|
|
48
|
+
const caps = {
|
|
49
|
+
platformName: "Android",
|
|
50
|
+
"appium:automationName": "UiAutomator2",
|
|
51
|
+
"appium:adbPort": adbPort,
|
|
52
|
+
"appium:deviceName": "Android Device",
|
|
53
|
+
"appium:appPackage": edge.pkg,
|
|
54
|
+
"appium:appActivity": edge.activity,
|
|
55
|
+
};
|
|
56
|
+
const findElementWithWaitForCondition = (strategy_1, selector_1, ...args_1) => __awaiter(this, [strategy_1, selector_1, ...args_1], void 0, function* (strategy, selector, timeout = 6000) {
|
|
57
|
+
try {
|
|
58
|
+
return yield (0, asyncbox_1.waitForCondition)(() => __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
try {
|
|
60
|
+
logger_js_1.default.info(`Attempting to find element (${strategy}: ${selector})`);
|
|
61
|
+
const element = yield driver.findElement(strategy, selector);
|
|
62
|
+
logger_js_1.default.info(`Successfully found element (${strategy}: ${selector})`);
|
|
63
|
+
return element;
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
// Return false to continue waiting
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}), {
|
|
70
|
+
waitMs: timeout,
|
|
71
|
+
intervalMs: 1000,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
throw new Error(`Failed to find element (${strategy}: ${selector}) within ${timeout}ms timeout: ${error.message}`);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
try {
|
|
79
|
+
yield driver.createSession(null, {
|
|
80
|
+
alwaysMatch: caps,
|
|
81
|
+
firstMatch: [{}],
|
|
82
|
+
});
|
|
83
|
+
const activity = yield driver.getCurrentActivity();
|
|
84
|
+
logger_js_1.default.info(`Activity is ${activity}`);
|
|
85
|
+
if (activity.includes('MicrosoftFirstRunActivity')) {
|
|
86
|
+
// wait for the page to load
|
|
87
|
+
yield new Promise(resolve => setTimeout(resolve, 5000));
|
|
88
|
+
const MAX_RETRIES = 3;
|
|
89
|
+
let attempt = 0;
|
|
90
|
+
let clicked = false;
|
|
91
|
+
let found = false;
|
|
92
|
+
var notNowButton;
|
|
93
|
+
while (attempt < MAX_RETRIES && !clicked) {
|
|
94
|
+
try {
|
|
95
|
+
notNowButton = yield findElementWithWaitForCondition('xpath', '//android.widget.Button[@text="Not now"]', 15000);
|
|
96
|
+
logger_js_1.default.info(`Not Now button is ${JSON.stringify(notNowButton, null, 2)}`);
|
|
97
|
+
found = true;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
logger_js_1.default.info(`Not Now button not found, retrying ...`);
|
|
101
|
+
}
|
|
102
|
+
finally {
|
|
103
|
+
if (found) {
|
|
104
|
+
yield driver.click(notNowButton.ELEMENT);
|
|
105
|
+
clicked = true;
|
|
106
|
+
}
|
|
107
|
+
attempt++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
attempt = 0;
|
|
111
|
+
clicked = false;
|
|
112
|
+
found = false;
|
|
113
|
+
var checkBox;
|
|
114
|
+
while (attempt < MAX_RETRIES && !clicked) {
|
|
115
|
+
try {
|
|
116
|
+
checkBox = yield findElementWithWaitForCondition('xpath', '//android.widget.Image');
|
|
117
|
+
logger_js_1.default.info(`Check box is ${JSON.stringify(checkBox, null, 2)}`);
|
|
118
|
+
found = true;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
logger_js_1.default.info(`Check box not found, retrying the other xpath...`);
|
|
122
|
+
try {
|
|
123
|
+
checkBox = yield findElementWithWaitForCondition('xpath', '//android.widget.CheckBox[@text="Help improve Microsoft products by sending optional diagnostic data about how you use the browser, websites you visit, and crash reports."]');
|
|
124
|
+
logger_js_1.default.info(`Check box is ${JSON.stringify(checkBox, null, 2)}`);
|
|
125
|
+
found = true;
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
logger_js_1.default.info(`Check box not found, retrying...`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
if (found) {
|
|
133
|
+
yield driver.click(checkBox.ELEMENT);
|
|
134
|
+
clicked = true;
|
|
135
|
+
}
|
|
136
|
+
attempt++;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
attempt = 0;
|
|
140
|
+
clicked = false;
|
|
141
|
+
found = false;
|
|
142
|
+
var confirmButton;
|
|
143
|
+
while (attempt < MAX_RETRIES && !clicked) {
|
|
144
|
+
try {
|
|
145
|
+
confirmButton = yield findElementWithWaitForCondition('xpath', '//android.widget.Button[@text="Confirm"]');
|
|
146
|
+
logger_js_1.default.info(`Confirm button is ${JSON.stringify(confirmButton, null, 2)}`);
|
|
147
|
+
found = true;
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
logger_js_1.default.info(`Confirm button not found, retrying...`);
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
if (found) {
|
|
154
|
+
yield driver.click(confirmButton.ELEMENT);
|
|
155
|
+
clicked = true;
|
|
156
|
+
}
|
|
157
|
+
attempt++;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
yield driver.deleteSession();
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
caps["appium:noReset"] = true;
|
|
167
|
+
yield driver.createSession(null, {
|
|
168
|
+
alwaysMatch: caps,
|
|
169
|
+
firstMatch: [{}],
|
|
170
|
+
});
|
|
171
|
+
const activity = yield driver.getCurrentActivity();
|
|
172
|
+
logger_js_1.default.info(`Activity is ${activity}`);
|
|
173
|
+
if (activity.includes('GrantPermissionsActivity')) {
|
|
174
|
+
// wait for the page to load
|
|
175
|
+
yield new Promise(resolve => setTimeout(resolve, 5000));
|
|
176
|
+
const MAX_RETRIES = 3;
|
|
177
|
+
let attempt = 0;
|
|
178
|
+
let clicked = false;
|
|
179
|
+
let found = false;
|
|
180
|
+
var denyButton;
|
|
181
|
+
while (attempt < MAX_RETRIES && !clicked) {
|
|
182
|
+
try {
|
|
183
|
+
denyButton = yield findElementWithWaitForCondition('id', 'com.android.permissioncontroller:id/permission_allow_button');
|
|
184
|
+
logger_js_1.default.info(`Deny button is ${JSON.stringify(denyButton, null, 2)}`);
|
|
185
|
+
found = true;
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
logger_js_1.default.info(`Deny button not found, retrying ...`);
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
if (found) {
|
|
192
|
+
yield driver.click(denyButton.ELEMENT);
|
|
193
|
+
clicked = true;
|
|
194
|
+
}
|
|
195
|
+
attempt++;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
logger_js_1.default.info(`walkthrough did not complete (${error.message}) — checking readiness anyway`);
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
yield (0, browserReady_js_1.finishSession)(driver, {
|
|
205
|
+
adb,
|
|
206
|
+
pkg: edge.pkg,
|
|
207
|
+
component: `${edge.pkg}/${edge.activity}`,
|
|
208
|
+
socket: 'chrome_devtools_remote',
|
|
209
|
+
selectors: [
|
|
210
|
+
'//android.widget.Button[@text="Confirm"]',
|
|
211
|
+
'//*[@resource-id="com.android.permissioncontroller:id/permission_allow_button"]',
|
|
212
|
+
],
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
218
|
+
yield skipWelcomeEdge();
|
|
219
|
+
process.exit(0);
|
|
220
|
+
}))();
|
|
221
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NjcmlwdHMvZWRnZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFFQSwyRUFBdUU7QUFDdkUsMkNBQWlDO0FBQ2pDLDBDQUErQztBQUMvQyxpRUFBbUM7QUFDbkMsdUNBQTRDO0FBQzVDLHVEQUFrRDtBQUVsRCxNQUFNLHVCQUF1QixHQUFHLEtBQUssQ0FBQztBQUV0QyxNQUFNLElBQUksR0FBRztJQUNYLEdBQUcsRUFBRSxvQkFBb0I7SUFDekIsUUFBUSxFQUFFLHlCQUF5QjtDQUNwQyxDQUFDO0FBRUYsTUFBTSxNQUFNLEdBQUc7SUFDYixZQUFZLEVBQUUsdUJBQXVCO0lBQ3JDLHVCQUF1QixFQUFFLGtCQUFrQjtDQUM1QyxDQUFDO0FBRUYsU0FBZSxlQUFlOztRQUM1QixNQUFNLE9BQU8sR0FBRyxJQUFBLHVCQUFjLEdBQUUsQ0FBQztRQUNqQyxNQUFNLEdBQUcsR0FBRyxNQUFNLGdCQUFHLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUM3QyxNQUFNLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN0RCw2RUFBNkU7UUFDN0UsOEVBQThFO1FBQzlFLDZFQUE2RTtRQUM3RSwrRUFBK0U7UUFDL0UseUVBQXlFO1FBQ3pFLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsS0FBSyxHQUFHLEVBQUUsQ0FBQztZQUMvQyxNQUFNLEdBQUcsQ0FBQyxPQUFPLENBQUM7Z0JBQ2hCLE9BQU87Z0JBQ1AsNkVBQTZFO2FBQzlFLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxNQUFNLE1BQU0sR0FBRyxJQUFJLHNEQUF5QixFQUFFLENBQUM7UUFDL0MsTUFBTSxJQUFJLEdBQUc7WUFDWCxZQUFZLEVBQUUsU0FBUztZQUN2Qix1QkFBdUIsRUFBRSxjQUFjO1lBQ3ZDLGdCQUFnQixFQUFFLE9BQU87WUFDekIsbUJBQW1CLEVBQUUsZ0JBQWdCO1lBQ3JDLG1CQUFtQixFQUFFLElBQUksQ0FBQyxHQUFHO1lBQzdCLG9CQUFvQixFQUFFLElBQUksQ0FBQyxRQUFRO1NBQ3BDLENBQUM7UUFFRixNQUFNLCtCQUErQixHQUFHLG9DQUl0QyxFQUFFLHlFQUhGLFFBQVEsRUFDUixRQUFRLEVBQ1IsT0FBTyxHQUFHLElBQUk7WUFFZCxJQUFJLENBQUM7Z0JBQ0gsT0FBTyxNQUFNLElBQUEsMkJBQWdCLEVBQzNCLEdBQVMsRUFBRTtvQkFDVCxJQUFJLENBQUM7d0JBQ0gsbUJBQUcsQ0FBQyxJQUFJLENBQ04sK0JBQStCLFFBQVEsS0FBSyxRQUFRLEdBQUcsQ0FDeEQsQ0FBQzt3QkFDRixNQUFNLE9BQU8sR0FBRyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO3dCQUM3RCxtQkFBRyxDQUFDLElBQUksQ0FDTiwrQkFBK0IsUUFBUSxLQUFLLFFBQVEsR0FBRyxDQUN4RCxDQUFDO3dCQUNGLE9BQU8sT0FBTyxDQUFDO29CQUNqQixDQUFDO29CQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7d0JBQ2YsbUNBQW1DO3dCQUNuQyxPQUFPLEtBQUssQ0FBQztvQkFDZixDQUFDO2dCQUNILENBQUMsQ0FBQSxFQUNEO29CQUNFLE1BQU0sRUFBRSxPQUFPO29CQUNmLFVBQVUsRUFBRSxJQUFJO2lCQUNqQixDQUNGLENBQUM7WUFDSixDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixNQUFNLElBQUksS0FBSyxDQUNiLDJCQUEyQixRQUFRLEtBQUssUUFBUSxZQUFZLE9BQU8sZUFBZSxLQUFLLENBQUMsT0FBTyxFQUFFLENBQ2xHLENBQUM7WUFDSixDQUFDO1FBQ0gsQ0FBQyxDQUFBLENBQUM7UUFHRixJQUFJLENBQUM7WUFDSCxNQUFNLE1BQU0sQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFO2dCQUMvQixXQUFXLEVBQUUsSUFBSTtnQkFDakIsVUFBVSxFQUFFLENBQUMsRUFBRSxDQUFDO2FBQ2pCLENBQUMsQ0FBQztZQUNILE1BQU0sUUFBUSxHQUFHLE1BQU0sTUFBTSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDbkQsbUJBQUcsQ0FBQyxJQUFJLENBQUMsZUFBZSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQ3BDLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQywyQkFBMkIsQ0FBQyxFQUFFLENBQUM7Z0JBQ25ELDRCQUE0QjtnQkFDNUIsTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztnQkFFeEQsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFDO2dCQUN0QixJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7Z0JBQ2hCLElBQUksT0FBTyxHQUFHLEtBQUssQ0FBQztnQkFDcEIsSUFBSSxLQUFLLEdBQUcsS0FBSyxDQUFDO2dCQUNsQixJQUFJLFlBQVksQ0FBQztnQkFFakIsT0FBTyxPQUFPLEdBQUcsV0FBVyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7b0JBQ3pDLElBQUcsQ0FBQzt3QkFDRixZQUFZLEdBQUcsTUFBTSwrQkFBK0IsQ0FDbEQsT0FBTyxFQUNQLDBDQUEwQyxFQUMxQyxLQUFLLENBQ04sQ0FBQzt3QkFDRixtQkFBRyxDQUFDLElBQUksQ0FBQyxxQkFBcUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQzt3QkFDdkUsS0FBSyxHQUFHLElBQUksQ0FBQztvQkFDZixDQUFDO29CQUFDLE9BQU0sS0FBSyxFQUFFLENBQUM7d0JBQ2QsbUJBQUcsQ0FBQyxJQUFJLENBQUMsd0NBQXdDLENBQUMsQ0FBQztvQkFDckQsQ0FBQzs0QkFBUyxDQUFDO3dCQUNULElBQUksS0FBSyxFQUFFLENBQUM7NEJBQ1YsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQzs0QkFDekMsT0FBTyxHQUFHLElBQUksQ0FBQzt3QkFDakIsQ0FBQzt3QkFDRCxPQUFPLEVBQUUsQ0FBQztvQkFDWixDQUFDO2dCQUNILENBQUM7Z0JBRUQsT0FBTyxHQUFHLENBQUMsQ0FBQztnQkFDWixPQUFPLEdBQUcsS0FBSyxDQUFDO2dCQUNoQixLQUFLLEdBQUcsS0FBSyxDQUFDO2dCQUNkLElBQUksUUFBUSxDQUFDO2dCQUViLE9BQU8sT0FBTyxHQUFHLFdBQVcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO29CQUN6QyxJQUFHLENBQUM7d0JBQ0YsUUFBUSxHQUFHLE1BQU0sK0JBQStCLENBQzlDLE9BQU8sRUFDUCx3QkFBd0IsQ0FDekIsQ0FBQzt3QkFDRixtQkFBRyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQzt3QkFDOUQsS0FBSyxHQUFHLElBQUksQ0FBQztvQkFDZixDQUFDO29CQUFDLE9BQU0sS0FBSyxFQUFFLENBQUM7d0JBQ2QsbUJBQUcsQ0FBQyxJQUFJLENBQUMsa0RBQWtELENBQUMsQ0FBQzt3QkFDN0QsSUFBSSxDQUFDOzRCQUNILFFBQVEsR0FBRyxNQUFNLCtCQUErQixDQUM5QyxPQUFPLEVBQ1AsOEtBQThLLENBQy9LLENBQUM7NEJBQ0YsbUJBQUcsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7NEJBQzlELEtBQUssR0FBRyxJQUFJLENBQUM7d0JBQ2YsQ0FBQzt3QkFBQyxPQUFNLEtBQUssRUFBRSxDQUFDOzRCQUNkLG1CQUFHLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLENBQUM7d0JBQy9DLENBQUM7b0JBQ0gsQ0FBQzs0QkFBUyxDQUFDO3dCQUNULElBQUksS0FBSyxFQUFFLENBQUM7NEJBQ1YsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQzs0QkFDckMsT0FBTyxHQUFHLElBQUksQ0FBQzt3QkFDakIsQ0FBQzt3QkFDRCxPQUFPLEVBQUUsQ0FBQztvQkFDWixDQUFDO2dCQUNILENBQUM7Z0JBRUQsT0FBTyxHQUFHLENBQUMsQ0FBQztnQkFDWixPQUFPLEdBQUcsS0FBSyxDQUFDO2dCQUNoQixLQUFLLEdBQUcsS0FBSyxDQUFDO2dCQUNkLElBQUksYUFBYSxDQUFDO2dCQUVsQixPQUFPLE9BQU8sR0FBRyxXQUFXLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztvQkFDekMsSUFBRyxDQUFDO3dCQUNGLGFBQWEsR0FBRyxNQUFNLCtCQUErQixDQUNuRCxPQUFPLEVBQ1AsMENBQTBDLENBQzNDLENBQUM7d0JBQ0YsbUJBQUcsQ0FBQyxJQUFJLENBQUMscUJBQXFCLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7d0JBQ3hFLEtBQUssR0FBRyxJQUFJLENBQUM7b0JBQ2YsQ0FBQztvQkFBQyxPQUFNLEtBQUssRUFBRSxDQUFDO3dCQUNkLG1CQUFHLENBQUMsSUFBSSxDQUFDLHVDQUF1QyxDQUFDLENBQUM7b0JBQ3BELENBQUM7NEJBQVMsQ0FBQzt3QkFDVCxJQUFJLEtBQUssRUFBRSxDQUFDOzRCQUNWLE1BQU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7NEJBQzFDLE9BQU8sR0FBRyxJQUFJLENBQUM7d0JBQ2pCLENBQUM7d0JBQ0QsT0FBTyxFQUFFLENBQUM7b0JBQ1osQ0FBQztnQkFDSCxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7Z0JBQVMsQ0FBQztZQUNULE1BQU0sTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQy9CLENBQUM7UUFFRCxJQUFJLENBQUM7WUFDSCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxJQUFJLENBQUM7WUFDOUIsTUFBTSxNQUFNLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRTtnQkFDL0IsV0FBVyxFQUFFLElBQUk7Z0JBQ2pCLFVBQVUsRUFBRSxDQUFDLEVBQUUsQ0FBQzthQUNqQixDQUFDLENBQUM7WUFDSCxNQUFNLFFBQVEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQ25ELG1CQUFHLENBQUMsSUFBSSxDQUFDLGVBQWUsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUNwQyxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsMEJBQTBCLENBQUMsRUFBRSxDQUFDO2dCQUNsRCw0QkFBNEI7Z0JBQzVCLE1BQU0sSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBRXhELE1BQU0sV0FBVyxHQUFHLENBQUMsQ0FBQztnQkFDdEIsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDO2dCQUNoQixJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7Z0JBQ3BCLElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQztnQkFDbEIsSUFBSSxVQUFVLENBQUM7Z0JBRWYsT0FBTyxPQUFPLEdBQUcsV0FBVyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7b0JBQ3pDLElBQUcsQ0FBQzt3QkFDRixVQUFVLEdBQUcsTUFBTSwrQkFBK0IsQ0FDaEQsSUFBSSxFQUNKLDZEQUE2RCxDQUM5RCxDQUFDO3dCQUNGLG1CQUFHLENBQUMsSUFBSSxDQUFDLGtCQUFrQixJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO3dCQUNsRSxLQUFLLEdBQUcsSUFBSSxDQUFDO29CQUNmLENBQUM7b0JBQUMsT0FBTSxLQUFLLEVBQUUsQ0FBQzt3QkFDZCxtQkFBRyxDQUFDLElBQUksQ0FBQyxxQ0FBcUMsQ0FBQyxDQUFDO29CQUNsRCxDQUFDOzRCQUFTLENBQUM7d0JBQ1QsSUFBSSxLQUFLLEVBQUUsQ0FBQzs0QkFDVixNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDOzRCQUN2QyxPQUFPLEdBQUcsSUFBSSxDQUFDO3dCQUNqQixDQUFDO3dCQUNELE9BQU8sRUFBRSxDQUFDO29CQUNaLENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLG1CQUFHLENBQUMsSUFBSSxDQUFDLGlDQUFpQyxLQUFLLENBQUMsT0FBTywrQkFBK0IsQ0FBQyxDQUFDO1FBQzFGLENBQUM7Z0JBQVMsQ0FBQztZQUNULE1BQU0sSUFBQSwrQkFBYSxFQUFDLE1BQU0sRUFBRTtnQkFDMUIsR0FBRztnQkFDSCxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUc7Z0JBQ2IsU0FBUyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUN6QyxNQUFNLEVBQUUsd0JBQXdCO2dCQUNoQyxTQUFTLEVBQUU7b0JBQ1QsMENBQTBDO29CQUMxQyxpRkFBaUY7aUJBQ2xGO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUlILENBQUM7Q0FBQTtBQUVELENBQUMsR0FBUyxFQUFFO0lBQ1YsTUFBTSxlQUFlLEVBQUUsQ0FBQztJQUN4QixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2xCLENBQUMsQ0FBQSxDQUFDLEVBQUUsQ0FBQyJ9
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
const appium_uiautomator2_driver_1 = require("appium-uiautomator2-driver");
|
|
17
|
+
const appium_adb_1 = require("appium-adb");
|
|
18
|
+
const adb_js_1 = require("../src/adb.js");
|
|
19
|
+
const logger_js_1 = __importDefault(require("../src/logger.js"));
|
|
20
|
+
const asyncbox_1 = require("asyncbox");
|
|
21
|
+
const browserReady_js_1 = require("./browserReady.js");
|
|
22
|
+
const START_APP_WAIT_DURATION = 60000;
|
|
23
|
+
const opera = {
|
|
24
|
+
pkg: 'com.opera.browser',
|
|
25
|
+
activity: 'com.opera.android.BrowserActivity',
|
|
26
|
+
};
|
|
27
|
+
const common = {
|
|
28
|
+
waitDuration: START_APP_WAIT_DURATION,
|
|
29
|
+
optionalIntentArguments: '-d www.appium.io',
|
|
30
|
+
};
|
|
31
|
+
function skipWelcomeOpera() {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
const adbPort = (0, adb_js_1.resolveAdbPort)();
|
|
34
|
+
const adb = yield appium_adb_1.ADB.createADB({ adbPort });
|
|
35
|
+
yield adb.adbExec(['shell', 'pm', 'clear', 'com.opera.browser']);
|
|
36
|
+
//await adb.startApp(Object.assign({}, opera, common));
|
|
37
|
+
const driver = new appium_uiautomator2_driver_1.AndroidUiautomator2Driver();
|
|
38
|
+
const caps = {
|
|
39
|
+
platformName: "Android",
|
|
40
|
+
"appium:automationName": "UiAutomator2",
|
|
41
|
+
"appium:adbPort": adbPort,
|
|
42
|
+
"appium:deviceName": "Android Device",
|
|
43
|
+
"appium:appPackage": "com.opera.browser",
|
|
44
|
+
"appium:appActivity": "com.opera.android.BrowserActivity",
|
|
45
|
+
};
|
|
46
|
+
try {
|
|
47
|
+
yield driver.createSession(null, {
|
|
48
|
+
alwaysMatch: caps,
|
|
49
|
+
firstMatch: [{}],
|
|
50
|
+
});
|
|
51
|
+
const activity = yield driver.getCurrentActivity();
|
|
52
|
+
logger_js_1.default.info(`Activity is ${activity}`);
|
|
53
|
+
if (activity.includes('Welcome')) {
|
|
54
|
+
// Helper function to find element with waitForCondition
|
|
55
|
+
const findElementWithWaitForCondition = (strategy_1, selector_1, ...args_1) => __awaiter(this, [strategy_1, selector_1, ...args_1], void 0, function* (strategy, selector, timeout = 30000) {
|
|
56
|
+
try {
|
|
57
|
+
return yield (0, asyncbox_1.waitForCondition)(() => __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
try {
|
|
59
|
+
logger_js_1.default.info(`Attempting to find element (${strategy}: ${selector})`);
|
|
60
|
+
const element = yield driver.findElement(strategy, selector);
|
|
61
|
+
logger_js_1.default.info(`Successfully found element (${strategy}: ${selector})`);
|
|
62
|
+
return element;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
// Return false to continue waiting
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}), {
|
|
69
|
+
waitMs: timeout,
|
|
70
|
+
intervalMs: 2000,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
throw new Error(`Failed to find element (${strategy}: ${selector}) within ${timeout}ms timeout: ${error.message}`);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
// an Android system dialog (e.g. "System UI isn't responding") can cover the
|
|
78
|
+
// welcome screen, so this button is not guaranteed; readiness recovers
|
|
79
|
+
let nextButton = null;
|
|
80
|
+
try {
|
|
81
|
+
nextButton = yield findElementWithWaitForCondition('id', 'com.opera.browser:id/continue_button');
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
logger_js_1.default.info(`continue_button not present: ${error.message}`);
|
|
85
|
+
}
|
|
86
|
+
if (nextButton) {
|
|
87
|
+
yield (0, browserReady_js_1.clickSafely)(driver, nextButton);
|
|
88
|
+
}
|
|
89
|
+
const skipButton = yield findElementWithWaitForCondition('id', 'com.opera.browser:id/skip_button');
|
|
90
|
+
const MAX_RETRIES = 3;
|
|
91
|
+
let attempt = 0;
|
|
92
|
+
let found = false;
|
|
93
|
+
while (attempt < MAX_RETRIES && !found) {
|
|
94
|
+
yield (0, browserReady_js_1.clickSafely)(driver, skipButton);
|
|
95
|
+
try {
|
|
96
|
+
yield findElementWithWaitForCondition('xpath', '//android.widget.Button[@text="Enable notifications"]');
|
|
97
|
+
found = true;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
logger_js_1.default.info(`Enable notifications text not found, retrying skip...`);
|
|
101
|
+
attempt++;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const skipAgainButton = yield findElementWithWaitForCondition('id', 'com.opera.browser:id/skip_button');
|
|
105
|
+
attempt = 0;
|
|
106
|
+
found = false;
|
|
107
|
+
while (attempt < MAX_RETRIES && !found) {
|
|
108
|
+
yield (0, browserReady_js_1.clickSafely)(driver, skipAgainButton);
|
|
109
|
+
try {
|
|
110
|
+
yield findElementWithWaitForCondition('xpath', '//android.widget.Button[@text="Allow"]');
|
|
111
|
+
found = true;
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
logger_js_1.default.info(`Enable notifications text not found, retrying skip...`);
|
|
115
|
+
attempt++;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// the notification permission dialog is conditional
|
|
119
|
+
let allowButton = null;
|
|
120
|
+
try {
|
|
121
|
+
allowButton = yield findElementWithWaitForCondition('xpath', '//android.widget.Button[@text="Allow"]', 10000);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
logger_js_1.default.info('Allow dialog not shown, skipping');
|
|
125
|
+
}
|
|
126
|
+
if (allowButton) {
|
|
127
|
+
yield (0, browserReady_js_1.clickSafely)(driver, allowButton);
|
|
128
|
+
}
|
|
129
|
+
attempt = 0;
|
|
130
|
+
found = false;
|
|
131
|
+
while (attempt < MAX_RETRIES && !found) {
|
|
132
|
+
try {
|
|
133
|
+
const doneButton = yield findElementWithWaitForCondition('id', 'com.opera.browser:id/positive_button', 8000);
|
|
134
|
+
yield (0, browserReady_js_1.clickSafely)(driver, doneButton);
|
|
135
|
+
found = true;
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
logger_js_1.default.info(`Done button not found, retrying after opening a url...`);
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
yield adb.shell(['am', 'start', '-a', 'android.intent.action.VIEW', '-d', 'https://www.appium.io', opera.pkg]);
|
|
142
|
+
attempt++;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
logger_js_1.default.info(`walkthrough did not complete (${error.message}) — checking readiness anyway`);
|
|
149
|
+
}
|
|
150
|
+
finally {
|
|
151
|
+
yield (0, browserReady_js_1.finishSession)(driver, {
|
|
152
|
+
adb,
|
|
153
|
+
pkg: opera.pkg,
|
|
154
|
+
component: `${opera.pkg}/${opera.activity}`,
|
|
155
|
+
socket: 'com.opera.browser.devtools',
|
|
156
|
+
selectors: [
|
|
157
|
+
'//android.widget.Button[@text="Accept and continue"]',
|
|
158
|
+
'//*[@resource-id="com.opera.browser:id/continue_button"]',
|
|
159
|
+
'//*[@resource-id="com.opera.browser:id/skip_button"]',
|
|
160
|
+
'//*[@resource-id="com.opera.browser:id/positive_button"]',
|
|
161
|
+
],
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
167
|
+
yield skipWelcomeOpera();
|
|
168
|
+
process.exit(0);
|
|
169
|
+
}))();
|
|
170
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlcmEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zY3JpcHRzL29wZXJhLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7OztBQUVBLDJFQUF1RTtBQUN2RSwyQ0FBaUM7QUFDakMsMENBQStDO0FBQy9DLGlFQUFtQztBQUNuQyx1Q0FBNEM7QUFDNUMsdURBQStEO0FBRS9ELE1BQU0sdUJBQXVCLEdBQUcsS0FBSyxDQUFDO0FBRXRDLE1BQU0sS0FBSyxHQUFHO0lBQ1osR0FBRyxFQUFFLG1CQUFtQjtJQUN4QixRQUFRLEVBQUUsbUNBQW1DO0NBQzlDLENBQUM7QUFFRixNQUFNLE1BQU0sR0FBRztJQUNiLFlBQVksRUFBRSx1QkFBdUI7SUFDckMsdUJBQXVCLEVBQUUsa0JBQWtCO0NBQzVDLENBQUM7QUFFRixTQUFlLGdCQUFnQjs7UUFDN0IsTUFBTSxPQUFPLEdBQUcsSUFBQSx1QkFBYyxHQUFFLENBQUM7UUFDakMsTUFBTSxHQUFHLEdBQUcsTUFBTSxnQkFBRyxDQUFDLFNBQVMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDN0MsTUFBTSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsbUJBQW1CLENBQUMsQ0FBQyxDQUFDO1FBQ2pFLHVEQUF1RDtRQUN2RCxNQUFNLE1BQU0sR0FBRyxJQUFJLHNEQUF5QixFQUFFLENBQUM7UUFDL0MsTUFBTSxJQUFJLEdBQUc7WUFDWCxZQUFZLEVBQUUsU0FBUztZQUN2Qix1QkFBdUIsRUFBRSxjQUFjO1lBQ3ZDLGdCQUFnQixFQUFFLE9BQU87WUFDekIsbUJBQW1CLEVBQUUsZ0JBQWdCO1lBQ3JDLG1CQUFtQixFQUFFLG1CQUFtQjtZQUN4QyxvQkFBb0IsRUFBRSxtQ0FBbUM7U0FDMUQsQ0FBQztRQUNGLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUU7Z0JBQy9CLFdB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
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
5
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
6
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
7
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
8
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
13
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
14
|
+
};
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
const appium_uiautomator2_driver_1 = require("appium-uiautomator2-driver");
|
|
17
|
+
const appium_adb_1 = require("appium-adb");
|
|
18
|
+
const adb_js_1 = require("../src/adb.js");
|
|
19
|
+
const logger_js_1 = __importDefault(require("../src/logger.js"));
|
|
20
|
+
const asyncbox_1 = require("asyncbox");
|
|
21
|
+
const browserReady_js_1 = require("./browserReady.js");
|
|
22
|
+
const START_APP_WAIT_DURATION = 60000;
|
|
23
|
+
const samsung = {
|
|
24
|
+
pkg: 'com.sec.android.app.sbrowser',
|
|
25
|
+
activity: 'com.sec.android.app.sbrowser.SBrowserMainActivity',
|
|
26
|
+
};
|
|
27
|
+
const common = {
|
|
28
|
+
waitDuration: START_APP_WAIT_DURATION,
|
|
29
|
+
optionalIntentArguments: '-d www.appium.io',
|
|
30
|
+
};
|
|
31
|
+
function skipWelcomeSamsung() {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
const adbPort = (0, adb_js_1.resolveAdbPort)();
|
|
34
|
+
const adb = yield appium_adb_1.ADB.createADB({ adbPort });
|
|
35
|
+
yield adb.adbExec(['shell', 'pm', 'clear', samsung.pkg]);
|
|
36
|
+
const driver = new appium_uiautomator2_driver_1.AndroidUiautomator2Driver();
|
|
37
|
+
const caps = {
|
|
38
|
+
platformName: "Android",
|
|
39
|
+
"appium:automationName": "UiAutomator2",
|
|
40
|
+
"appium:adbPort": adbPort,
|
|
41
|
+
"appium:deviceName": "Android Device",
|
|
42
|
+
"appium:appPackage": samsung.pkg,
|
|
43
|
+
"appium:appActivity": samsung.activity,
|
|
44
|
+
};
|
|
45
|
+
try {
|
|
46
|
+
yield driver.createSession(null, {
|
|
47
|
+
alwaysMatch: caps,
|
|
48
|
+
firstMatch: [{}],
|
|
49
|
+
});
|
|
50
|
+
const activity = yield driver.getCurrentActivity();
|
|
51
|
+
logger_js_1.default.info(`Activity is ${activity}`);
|
|
52
|
+
if (activity.includes('HelpIntroActivity')) {
|
|
53
|
+
const findElementWithWaitForCondition = (strategy_1, selector_1, ...args_1) => __awaiter(this, [strategy_1, selector_1, ...args_1], void 0, function* (strategy, selector, timeout = 6000) {
|
|
54
|
+
try {
|
|
55
|
+
return yield (0, asyncbox_1.waitForCondition)(() => __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
try {
|
|
57
|
+
logger_js_1.default.info(`Attempting to find element (${strategy}: ${selector})`);
|
|
58
|
+
const element = yield driver.findElement(strategy, selector);
|
|
59
|
+
logger_js_1.default.info(`Successfully found element (${strategy}: ${selector})`);
|
|
60
|
+
return element;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
// Return false to continue waiting
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
}), {
|
|
67
|
+
waitMs: timeout,
|
|
68
|
+
intervalMs: 1000,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
throw new Error(`Failed to find element (${strategy}: ${selector}) within ${timeout}ms timeout: ${error.message}`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
// The agree button is not the same on every build: newer intros label it
|
|
76
|
+
// "Continue" and do not expose help_intro_legal_agree_button. Try the id
|
|
77
|
+
// first, then the label.
|
|
78
|
+
//
|
|
79
|
+
// Note the intro also carries a "Close app" button beside it, and a
|
|
80
|
+
// SystemUI ANR dialog ("Close app" / "Wait") can sit on top of the whole
|
|
81
|
+
// screen. Only ever match the affordances below by exact text — clicking
|
|
82
|
+
// "Close app" would kill the browser we are setting up.
|
|
83
|
+
const INTRO_SELECTORS = [
|
|
84
|
+
['id', 'com.sec.android.app.sbrowser:id/help_intro_legal_agree_button'],
|
|
85
|
+
['xpath', '//android.widget.Button[@text="Continue"]'],
|
|
86
|
+
['xpath', '//android.widget.Button[@text="Agree"]'],
|
|
87
|
+
];
|
|
88
|
+
const MAX_RETRIES = 2;
|
|
89
|
+
let attempt = 0;
|
|
90
|
+
while (attempt < MAX_RETRIES) {
|
|
91
|
+
let clicked = false;
|
|
92
|
+
for (const [strategy, selector] of INTRO_SELECTORS) {
|
|
93
|
+
try {
|
|
94
|
+
const buttonToClick = yield findElementWithWaitForCondition(strategy, selector, 4000);
|
|
95
|
+
yield driver.click(buttonToClick.ELEMENT);
|
|
96
|
+
logger_js_1.default.info(`intro dismissed via ${strategy}: ${selector}`);
|
|
97
|
+
clicked = true;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
// try the next shape
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (!clicked) {
|
|
105
|
+
logger_js_1.default.info('intro button not found on this attempt');
|
|
106
|
+
}
|
|
107
|
+
attempt++;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Samsung shows a privacy-notice alert on SBrowserMainActivity, after the
|
|
111
|
+
// intro rather than as part of it, so the branch above never sees it. It does
|
|
112
|
+
// not block the devtools socket — the page loads underneath — so the
|
|
113
|
+
// readiness pass has nothing to react to and the dialog would sit over the
|
|
114
|
+
// page for the whole session, swallowing taps meant for the content.
|
|
115
|
+
for (const selector of [
|
|
116
|
+
'//android.widget.Button[@resource-id="android:id/button1" and @text="Continue"]',
|
|
117
|
+
'//android.widget.Button[@text="Continue"]',
|
|
118
|
+
]) {
|
|
119
|
+
try {
|
|
120
|
+
const dialogButton = yield driver.findElement('xpath', selector);
|
|
121
|
+
yield driver.click(dialogButton.ELEMENT);
|
|
122
|
+
logger_js_1.default.info(`dismissed post-intro dialog via ${selector}`);
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
// not shown on this launch
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
logger_js_1.default.info(`walkthrough did not complete (${error.message}) — checking readiness anyway`);
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
yield (0, browserReady_js_1.finishSession)(driver, {
|
|
135
|
+
adb,
|
|
136
|
+
pkg: samsung.pkg,
|
|
137
|
+
component: `${samsung.pkg}/${samsung.activity}`,
|
|
138
|
+
socket: 'Terrace_devtools_remote',
|
|
139
|
+
selectors: [
|
|
140
|
+
'//*[@resource-id="com.sec.android.app.sbrowser:id/help_intro_legal_agree_button"]',
|
|
141
|
+
'//android.widget.Button[@text="Agree"]',
|
|
142
|
+
'//android.widget.Button[@text="I agree"]',
|
|
143
|
+
],
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
149
|
+
yield skipWelcomeSamsung();
|
|
150
|
+
process.exit(0);
|
|
151
|
+
}))();
|
|
152
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Ftc3VuZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NjcmlwdHMvc2Ftc3VuZy5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFFQSwyRUFBdUU7QUFDdkUsMkNBQWlDO0FBQ2pDLDBDQUErQztBQUMvQyxpRUFBbUM7QUFDbkMsdUNBQTRDO0FBQzVDLHVEQUFrRDtBQUVsRCxNQUFNLHVCQUF1QixHQUFHLEtBQUssQ0FBQztBQUV0QyxNQUFNLE9BQU8sR0FBRztJQUNkLEdBQUcsRUFBRSw4QkFBOEI7SUFDbkMsUUFBUSxFQUFFLG1EQUFtRDtDQUM5RCxDQUFDO0FBRUYsTUFBTSxNQUFNLEdBQUc7SUFDYixZQUFZLEVBQUUsdUJBQXVCO0lBQ3JDLHVCQUF1QixFQUFFLGtCQUFrQjtDQUM1QyxDQUFDO0FBRUYsU0FBZSxrQkFBa0I7O1FBQy9CLE1BQU0sT0FBTyxHQUFHLElBQUEsdUJBQWMsR0FBRSxDQUFDO1FBQ2pDLE1BQU0sR0FBRyxHQUFHLE1BQU0sZ0JBQUcsQ0FBQyxTQUFTLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzdDLE1BQU0sR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3pELE1BQU0sTUFBTSxHQUFHLElBQUksc0RBQXlCLEVBQUUsQ0FBQztRQUMvQyxNQUFNLElBQUksR0FBRztZQUNYLFlBQVksRUFBRSxTQUFTO1lBQ3ZCLHVCQUF1QixFQUFFLGNBQWM7WUFDdkMsZ0JBQWdCLEVBQUUsT0FBTztZQUN6QixtQkFBbUIsRUFBRSxnQkFBZ0I7WUFDckMsbUJBQW1CLEVBQUUsT0FBTyxDQUFDLEdBQUc7WUFDaEMsb0JBQW9CLEVBQUUsT0FBTyxDQUFDLFFBQVE7U0FDdkMsQ0FBQztRQUNGLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJ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
|