diff --git a/android-types-internal.d.ts b/android-types-internal.d.ts index ec9e1b6dbd..9f81843d7b 100644 --- a/android-types-internal.d.ts +++ b/android-types-internal.d.ts @@ -26,7 +26,7 @@ export interface AndroidDevice exte serial(): string; model(): string; webViews(): AndroidWebView[]; - webView(selector: { pkg: string }): Promise>; + webView(selector: { pkg: string }, options?: { timeout?: number }): Promise>; shell(command: string): Promise; launchBrowser(options?: BrowserContextOptions & { packageName?: string }): Promise; close(): Promise; diff --git a/packages/build_package.js b/packages/build_package.js index 50d360594e..34446b5111 100755 --- a/packages/build_package.js +++ b/packages/build_package.js @@ -65,7 +65,7 @@ const PACKAGES = { files: [...PLAYWRIGHT_CORE_FILES, ...FFMPEG_FILES, 'electron-types.d.ts'], }, 'playwright-android': { - version: '0.0.7', // Manually manage playwright-android version. + version: '0.0.8', // Manually manage playwright-android version. description: 'A high-level API to automate Chrome for Android', browsers: [], files: [...PLAYWRIGHT_CORE_FILES, ...FFMPEG_FILES, 'android-types.d.ts', 'android-types-internal.d.ts', 'bin/android-driver.apk', 'bin/android-driver-target.apk'], diff --git a/test/android/android.fixtures.ts b/test/android/android.fixtures.ts new file mode 100644 index 0000000000..c747a9d992 --- /dev/null +++ b/test/android/android.fixtures.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2020 Microsoft Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { Android, AndroidDevice } from '../../android-types'; +import { folio as baseFolio } from '../fixtures'; + +const fixtures = baseFolio.extend<{ + device: AndroidDevice + }, { + android: Android, + }>(); + +fixtures.device.init(async ({ playwright }, runTest) => { + const [device] = await playwright._android.devices(); + await device.shell('am force-stop org.chromium.webview_shell'); + await device.shell('am force-stop com.android.chrome'); + await runTest(device); + device.close(); +}); + +export const folio = fixtures.build(); diff --git a/test/android/browser.spec.ts b/test/android/browser.spec.ts new file mode 100644 index 0000000000..3079d0533c --- /dev/null +++ b/test/android/browser.spec.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2020 Microsoft Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { folio } from './android.fixtures'; +const { it, expect } = folio; + +if (process.env.PW_ANDROID_TESTS) { + it('should discover device', async function({ device }) { + expect(device.model()).toBe('sdk_gphone_x86_arm'); + }); + + it('should launch browser', async function({ device }) { + const context = await device.launchBrowser(); + const [page] = context.pages(); + await page.goto('data:text/html,Hello world!'); + expect(await page.title()).toBe('Hello world!'); + await context.close(); + }); +} diff --git a/test/android/webview.spec.ts b/test/android/webview.spec.ts new file mode 100644 index 0000000000..d96a609e12 --- /dev/null +++ b/test/android/webview.spec.ts @@ -0,0 +1,58 @@ +/** + * Copyright 2020 Microsoft Corporation. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { folio } from './android.fixtures'; +const { it, expect } = folio; + +if (process.env.PW_ANDROID_TESTS) { + it('should discover webviews', async function({ device }) { + expect(device.webViews().length).toBe(0); + await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity'); + const webview = await device.webView({ pkg: 'org.chromium.webview_shell' }); + expect(webview.pkg()).toBe('org.chromium.webview_shell'); + }); + + it('should connect to page', async function({ device }) { + expect(device.webViews().length).toBe(0); + await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity'); + const webview = await device.webView({ pkg: 'org.chromium.webview_shell' }); + const page = await webview.page(); + expect(page.url()).toBe('about:blank'); + }); + + it('should navigate page externally', async function({ device, server }) { + expect(device.webViews().length).toBe(0); + await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity'); + const webview = await device.webView({ pkg: 'org.chromium.webview_shell' }); + const page = await webview.page(); + await page.goto('data:text/html,Hello world!'); + expect(await page.title()).toBe('Hello world!'); + }); + + it('should navigate page externally', async function({ device, server }) { + expect(device.webViews().length).toBe(0); + await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity'); + const webview = await device.webView({ pkg: 'org.chromium.webview_shell' }); + const page = await webview.page(); + + await device.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'data:text/html,Hello world!'); + await Promise.all([ + page.waitForNavigation(), + device.press({ res: 'org.chromium.webview_shell:id/url_field' }, 'Enter') + ]); + expect(await page.title()).toBe('Hello world!'); + }); +} diff --git a/test/electron/electron.fixture.ts b/test/electron/electron.fixture.ts index 6b23c22ee7..cdece774da 100644 --- a/test/electron/electron.fixture.ts +++ b/test/electron/electron.fixture.ts @@ -15,7 +15,7 @@ */ import { folio as base } from '../fixtures'; -import type { ElectronApplication, ElectronLauncher, ElectronPage } from '../../electron-types'; +import type { ElectronApplication, ElectronPage } from '../../electron-types'; import path from 'path'; const electronName = process.platform === 'win32' ? 'electron.cmd' : 'electron'; @@ -42,7 +42,3 @@ fixtures.window.init(async ({ application }, run) => { }); export const folio = fixtures.build(); - -declare module '../../index' { - const _electron: ElectronLauncher; -} diff --git a/test/fixtures.ts b/test/fixtures.ts index 76f0fb24ee..ed43163ce7 100644 --- a/test/fixtures.ts +++ b/test/fixtures.ts @@ -27,6 +27,8 @@ import { installCoverageHooks } from './coverage'; import { folio as httpFolio } from './http.fixtures'; import { folio as playwrightFolio } from './playwright.fixtures'; import { PlaywrightClient } from '../lib/remote/playwrightClient'; +import type { Android } from '../android-types'; +import type { ElectronLauncher } from '../electron-types'; export { expect, config } from 'folio'; const removeFolderAsync = util.promisify(require('rimraf')); @@ -189,3 +191,9 @@ export const beforeEach = folio.beforeEach; export const afterEach = folio.afterEach; export const beforeAll = folio.beforeAll; export const afterAll = folio.afterAll; + + +declare module '../index' { + const _android: Android; + const _electron: ElectronLauncher; +} diff --git a/utils/avd_start.sh b/utils/avd_start.sh index 93866cdf42..1962fcc2ec 100755 --- a/utils/avd_start.sh +++ b/utils/avd_start.sh @@ -5,4 +5,4 @@ export ANDROID_SDK_ROOT=${SDKDIR} export ANDROID_HOME=${SDKDIR} export ANDROID_AVD_HOME=${SDKDIR}/avd -${SDKDIR}/emulator/emulator -avd android30 -gpu guest +${SDKDIR}/emulator/emulator -avd android30 -gpu swiftshader_indirect