Skip to content

Commit 4799e8f

Browse files
authored
feat(adb): add screenshot (#4701)
1 parent 1596b53 commit 4799e8f

File tree

13 files changed

+63
-12
lines changed

13 files changed

+63
-12
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,10 @@ jobs:
246246
run: utils/avd_recreate.sh
247247
- name: Start Android Emulator
248248
run: utils/avd_start.sh
249-
- run: npx folio test/android -p browserName=chromium --workers=1 --forbid-only --global-timeout=5400000 --retries=3 --reporter=dot,json
249+
- run: npx folio test/android -p browserName=chromium --workers=1 --forbid-only --timeout=60000 --global-timeout=5400000 --retries=3 --reporter=dot,json
250250
env:
251251
FOLIO_JSON_OUTPUT_NAME: "test-results/report.json"
252252
PW_ANDROID_TESTS: 1
253-
DEBUG: pw:api
254253
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
255254
if: always() && github.ref == 'refs/heads/master'
256255
- uses: actions/upload-artifact@v1

android-types-internal.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export interface AndroidDevice<BrowserContextOptions, BrowserContext, Page> exte
4747
swipe(selector: AndroidSelector, direction: 'down' | 'up' | 'left' | 'right', percent: number, options?: { speed?: number } & { timeout?: number }): Promise<void>;
4848

4949
info(selector: AndroidSelector): Promise<AndroidElementInfo>;
50+
screenshot(options?: { path?: string }): Promise<Buffer>;
5051
}
5152

5253
export interface AndroidSocket extends EventEmitter {

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"ctest": "cross-env BROWSER=chromium folio test/",
1313
"ftest": "cross-env BROWSER=firefox folio test/",
1414
"wtest": "cross-env BROWSER=webkit folio test/",
15+
"atest": "cross-env BROWSER=chromium PW_ANDROID_TESTS=1 npx folio test/android --workers=1 --reporter=list",
1516
"test": "folio test/",
1617
"eslint": "[ \"$CI\" = true ] && eslint --quiet -f codeframe --ext js,ts . || eslint --ext js,ts .",
1718
"tsc": "tsc -p .",
@@ -31,8 +32,7 @@
3132
"roll-browser": "node utils/roll_browser.js",
3233
"coverage": "node test/checkCoverage.js",
3334
"check-deps": "node utils/check_deps.js",
34-
"build-android-driver": "./utils/build_android_driver.sh",
35-
"test-android-driver": "PW_ANDROID_TESTS=1 npx folio test/android -p browserName=chromium --workers=1"
35+
"build-android-driver": "./utils/build_android_driver.sh"
3636
},
3737
"author": {
3838
"name": "Microsoft Corporation"

src/client/android.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,16 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel, c
191191
});
192192
}
193193

194+
async screenshot(options: { path?: string } = {}): Promise<Buffer> {
195+
return await this._wrapApiCall('androidDevice.screenshot', async () => {
196+
const { binary } = await this._channel.screenshot();
197+
const buffer = Buffer.from(binary, 'base64');
198+
if (options.path)
199+
await util.promisify(fs.writeFile)(options.path, buffer);
200+
return buffer;
201+
});
202+
}
203+
194204
async close() {
195205
return this._wrapApiCall('androidDevice.close', async () => {
196206
await this._channel.close();

src/dispatchers/androidDispatcher.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ export class AndroidDeviceDispatcher extends Dispatcher<AndroidDevice, channels.
136136
await this._object.send('inputDrag', params);
137137
}
138138

139+
async screenshot(params: channels.AndroidDeviceScreenshotParams): Promise<channels.AndroidDeviceScreenshotResult> {
140+
return { binary: (await this._object.screenshot()).toString('base64') };
141+
}
142+
139143
async shell(params: channels.AndroidDeviceShellParams): Promise<channels.AndroidDeviceShellResult> {
140144
return { result: (await this._object.shell(params.command)).toString('base64') };
141145
}

src/protocol/channels.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2462,6 +2462,7 @@ export interface AndroidDeviceChannel extends Channel {
24622462
swipe(params: AndroidDeviceSwipeParams, metadata?: Metadata): Promise<AndroidDeviceSwipeResult>;
24632463
info(params: AndroidDeviceInfoParams, metadata?: Metadata): Promise<AndroidDeviceInfoResult>;
24642464
tree(params?: AndroidDeviceTreeParams, metadata?: Metadata): Promise<AndroidDeviceTreeResult>;
2465+
screenshot(params?: AndroidDeviceScreenshotParams, metadata?: Metadata): Promise<AndroidDeviceScreenshotResult>;
24652466
inputType(params: AndroidDeviceInputTypeParams, metadata?: Metadata): Promise<AndroidDeviceInputTypeResult>;
24662467
inputPress(params: AndroidDeviceInputPressParams, metadata?: Metadata): Promise<AndroidDeviceInputPressResult>;
24672468
inputTap(params: AndroidDeviceInputTapParams, metadata?: Metadata): Promise<AndroidDeviceInputTapResult>;
@@ -2601,6 +2602,11 @@ export type AndroidDeviceTreeOptions = {};
26012602
export type AndroidDeviceTreeResult = {
26022603
tree: AndroidElementInfo,
26032604
};
2605+
export type AndroidDeviceScreenshotParams = {};
2606+
export type AndroidDeviceScreenshotOptions = {};
2607+
export type AndroidDeviceScreenshotResult = {
2608+
binary: Binary,
2609+
};
26042610
export type AndroidDeviceInputTypeParams = {
26052611
text: string,
26062612
};

src/protocol/protocol.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2204,6 +2204,10 @@ AndroidDevice:
22042204
returns:
22052205
tree: AndroidElementInfo
22062206

2207+
screenshot:
2208+
returns:
2209+
binary: binary
2210+
22072211
inputType:
22082212
parameters:
22092213
text: string

src/protocol/validator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
966966
selector: tType('AndroidSelector'),
967967
});
968968
scheme.AndroidDeviceTreeParams = tOptional(tObject({}));
969+
scheme.AndroidDeviceScreenshotParams = tOptional(tObject({}));
969970
scheme.AndroidDeviceInputTypeParams = tObject({
970971
text: tString,
971972
});

src/server/android/android.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ export class AndroidDevice extends EventEmitter {
148148
return await this._backend.open(`${command}`);
149149
}
150150

151+
async screenshot(): Promise<Buffer> {
152+
return await this._backend.runCommand(`shell:screencap -p`);
153+
}
154+
151155
private async _driver(): Promise<Transport> {
152156
if (this._driverPromise)
153157
return this._driverPromise;

test/android/browser.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ import { folio } from './android.fixtures';
1818
const { it, expect } = folio;
1919

2020
if (process.env.PW_ANDROID_TESTS) {
21-
it('should discover device', async function({ device }) {
21+
it('androidDevice.model', async function({ device }) {
2222
expect(device.model()).toBe('sdk_gphone_x86_arm');
2323
});
2424

25-
it('should launch browser', async function({ device }) {
25+
it('androidDevice.launchBrowser', async function({ device }) {
2626
const context = await device.launchBrowser();
2727
const [page] = context.pages();
2828
await page.goto('data:text/html,<title>Hello world!</title>');

0 commit comments

Comments
 (0)