Skip to content

Commit

Permalink
test(android): run selected page tests on android (#5879)
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelfeldman authored Mar 19, 2021
1 parent cbebf64 commit ad5c028
Show file tree
Hide file tree
Showing 22 changed files with 188 additions and 178 deletions.
11 changes: 7 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ jobs:
test_android:
name: Android Emulator
runs-on: macos-10.15
env:
FOLIO_JSON_OUTPUT_NAME: "test-results/report.json"
PW_ANDROID_TESTS: 1
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
Expand All @@ -247,10 +250,10 @@ jobs:
run: utils/avd_recreate.sh
- name: Start Android Emulator
run: utils/avd_start.sh
- run: npx folio test/android -p browserName=chromium --workers=1 --forbid-only --timeout=120000 --global-timeout=5400000 --retries=3 --reporter=dot,json
env:
FOLIO_JSON_OUTPUT_NAME: "test-results/report.json"
PW_ANDROID_TESTS: 1
- name: Run device tests
run: npx folio test/android -p browserName=chromium --workers=1 --forbid-only --timeout=120000 --global-timeout=5400000 --retries=3 --reporter=dot,json
- name: Run page tests
run: npx folio test/page -p browserName=chromium --workers=1 --forbid-only --timeout=120000 --global-timeout=5400000 --retries=3 --reporter=dot,json
- run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json
if: always() && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-'))
- uses: actions/upload-artifact@v1
Expand Down
35 changes: 0 additions & 35 deletions test/android/android.fixtures.ts

This file was deleted.

22 changes: 11 additions & 11 deletions test/android/browser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,42 @@
* limitations under the License.
*/

import { folio } from './android.fixtures';
import { folio } from '../fixtures';
const { it, expect } = folio;

if (process.env.PW_ANDROID_TESTS) {
it('androidDevice.model', async function({ device }) {
expect(device.model()).toBe('sdk_gphone_x86_arm');
it('androidDevice.model', async function({ androidDevice }) {
expect(androidDevice.model()).toBe('sdk_gphone_x86_arm');
});

it('androidDevice.launchBrowser', async function({ device }) {
const context = await device.launchBrowser();
it('androidDevice.launchBrowser', async function({ androidDevice }) {
const context = await androidDevice.launchBrowser();
const [page] = context.pages();
await page.goto('data:text/html,<title>Hello world!</title>');
expect(await page.title()).toBe('Hello world!');
await context.close();
});

it('should create new page', async function({ device }) {
const context = await device.launchBrowser();
it('should create new page', async function({ androidDevice }) {
const context = await androidDevice.launchBrowser();
const page = await context.newPage();
await page.goto('data:text/html,<title>Hello world!</title>');
expect(await page.title()).toBe('Hello world!');
await page.close();
await context.close();
});

it('should check', async function({ device }) {
const context = await device.launchBrowser();
it('should check', async function({ androidDevice }) {
const context = await androidDevice.launchBrowser();
const [page] = context.pages();
await page.setContent(`<input id='checkbox' type='checkbox'></input>`);
await page.check('input');
expect(await page.evaluate(() => window['checkbox'].checked)).toBe(true);
await page.close();
await context.close();
});
it('should be able to send CDP messages', async ({ device }) => {
const context = await device.launchBrowser();
it('should be able to send CDP messages', async ({ androidDevice }) => {
const context = await androidDevice.launchBrowser();
const [page] = context.pages();
const client = await context.newCDPSession(page);
await client.send('Runtime.enable');
Expand Down
30 changes: 15 additions & 15 deletions test/android/device.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
import fs from 'fs';
import { PNG } from 'pngjs';

import { folio } from './android.fixtures';
import { folio } from '../fixtures';
const { it, expect } = folio;

if (process.env.PW_ANDROID_TESTS) {
it('androidDevice.shell', async function({ device }) {
const output = await device.shell('echo 123');
it('androidDevice.shell', async function({ androidDevice }) {
const output = await androidDevice.shell('echo 123');
expect(output.toString()).toBe('123\n');
});

it('androidDevice.open', async function({ device }) {
const socket = await device.open('shell:/bin/cat');
it('androidDevice.open', async function({ androidDevice }) {
const socket = await androidDevice.open('shell:/bin/cat');
await socket.write(Buffer.from('321\n'));
const output = await new Promise(resolve => socket.on('data', resolve));
expect(output.toString()).toBe('321\n');
Expand All @@ -36,28 +36,28 @@ if (process.env.PW_ANDROID_TESTS) {
await closedPromise;
});

it('androidDevice.screenshot', async function({ device, testInfo }) {
it('androidDevice.screenshot', async function({ androidDevice, testInfo }) {
const path = testInfo.outputPath('screenshot.png');
const result = await device.screenshot({ path });
const result = await androidDevice.screenshot({ path });
const buffer = fs.readFileSync(path);
expect(result.length).toBe(buffer.length);
const { width, height} = PNG.sync.read(result);
expect(width).toBe(1080);
expect(height).toBe(1920);
});

it('androidDevice.push', async function({ device, testInfo }) {
await device.shell('rm /data/local/tmp/hello-world');
await device.push(Buffer.from('hello world'), '/data/local/tmp/hello-world');
const data = await device.shell('cat /data/local/tmp/hello-world');
it('androidDevice.push', async function({ androidDevice }) {
await androidDevice.shell('rm /data/local/tmp/hello-world');
await androidDevice.push(Buffer.from('hello world'), '/data/local/tmp/hello-world');
const data = await androidDevice.shell('cat /data/local/tmp/hello-world');
expect(data).toEqual(Buffer.from('hello world'));
});

it('androidDevice.fill', test => {
test.fixme(!!process.env.CI, 'Hangs on the bots');
}, async function({ device }) {
await device.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
await device.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'Hello');
expect((await device.info({ res: 'org.chromium.webview_shell:id/url_field' })).text).toBe('Hello');
}, async function({ androidDevice }) {
await androidDevice.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
await androidDevice.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'Hello');
expect((await androidDevice.info({ res: 'org.chromium.webview_shell:id/url_field' })).text).toBe('Hello');
});
}
40 changes: 20 additions & 20 deletions test/android/webview.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,47 +14,47 @@
* limitations under the License.
*/

import { folio } from './android.fixtures';
import { folio } from '../fixtures';
const { it, expect } = folio;

if (process.env.PW_ANDROID_TESTS) {
it('androidDevice.webView', 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' });
it('androidDevice.webView', async function({ androidDevice }) {
expect(androidDevice.webViews().length).toBe(0);
await androidDevice.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
const webview = await androidDevice.webView({ pkg: 'org.chromium.webview_shell' });
expect(webview.pkg()).toBe('org.chromium.webview_shell');
expect(device.webViews().length).toBe(1);
expect(androidDevice.webViews().length).toBe(1);
});

it('webView.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' });
it('webView.page', async function({ androidDevice }) {
expect(androidDevice.webViews().length).toBe(0);
await androidDevice.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
const webview = await androidDevice.webView({ pkg: 'org.chromium.webview_shell' });
const page = await webview.page();
expect(page.url()).toBe('about:blank');
});

it('should navigate page internally', 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' });
it('should navigate page internally', async function({ androidDevice }) {
expect(androidDevice.webViews().length).toBe(0);
await androidDevice.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
const webview = await androidDevice.webView({ pkg: 'org.chromium.webview_shell' });
const page = await webview.page();
await page.goto('data:text/html,<title>Hello world!</title>');
expect(await page.title()).toBe('Hello world!');
});

it('should navigate page externally', test => {
test.fixme(!!process.env.CI, 'Hangs on the bots');
}, 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' });
}, async function({ androidDevice }) {
expect(androidDevice.webViews().length).toBe(0);
await androidDevice.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
const webview = await androidDevice.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,<title>Hello world!</title>');
await androidDevice.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'data:text/html,<title>Hello world!</title>');
await Promise.all([
page.waitForNavigation(),
device.press({ res: 'org.chromium.webview_shell:id/url_field' }, 'Enter')
androidDevice.press({ res: 'org.chromium.webview_shell:id/url_field' }, 'Enter')
]);
expect(await page.title()).toBe('Hello world!');
});
Expand Down
69 changes: 69 additions & 0 deletions test/browsercontext-add-init-script.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* Copyright 2018 Google Inc. All rights reserved.
* Modifications copyright (c) Microsoft Corporation.
*
* 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 { it, expect } from './fixtures';
import path from 'path';

it('should work with browser context scripts', async ({ context, server }) => {
await context.addInitScript(() => window['temp'] = 123);
const page = await context.newPage();
await page.addInitScript(() => window['injected'] = window['temp']);
await page.goto(server.PREFIX + '/tamperable.html');
expect(await page.evaluate(() => window['result'])).toBe(123);
});

it('should work without navigation, after all bindings', async ({ context }) => {
let callback;
const promise = new Promise(f => callback = f);
await context.exposeFunction('woof', function(arg) {
callback(arg);
});

await context.addInitScript(() => {
window['woof']('hey');
window['temp'] = 123;
});
const page = await context.newPage();

expect(await page.evaluate(() => window['temp'])).toBe(123);
expect(await promise).toBe('hey');
});

it('should work without navigation in popup', async ({ context }) => {
await context.addInitScript(() => window['temp'] = 123);
const page = await context.newPage();
const [popup] = await Promise.all([
page.waitForEvent('popup'),
page.evaluate(() => window['win'] = window.open()),
]);
expect(await popup.evaluate(() => window['temp'])).toBe(123);
});

it('should work with browser context scripts with a path', async ({ context, server }) => {
await context.addInitScript({ path: path.join(__dirname, 'assets/injectedfile.js') });
const page = await context.newPage();
await page.goto(server.PREFIX + '/tamperable.html');
expect(await page.evaluate(() => window['result'])).toBe(123);
});

it('should work with browser context scripts for already created pages', async ({ context, server }) => {
const page = await context.newPage();
await context.addInitScript(() => window['temp'] = 123);
await page.addInitScript(() => window['injected'] = window['temp']);
await page.goto(server.PREFIX + '/tamperable.html');
expect(await page.evaluate(() => window['result'])).toBe(123);
});
25 changes: 24 additions & 1 deletion test/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import fs from 'fs';
import path from 'path';
import util from 'util';
import os from 'os';
import type { Browser, BrowserContext, BrowserType, Page } from '../index';
import type { AndroidDevice, Browser, BrowserContext, BrowserType, Page } from '../index';
import { installCoverageHooks } from './coverage';
import { folio as httpFolio } from './http.fixtures';
import { folio as playwrightFolio } from './playwright.fixtures';
Expand All @@ -45,6 +45,8 @@ type ModeParameters = {
};
type WorkerFixtures = {
toImpl: (rpcObject: any) => any;
androidDevice: AndroidDevice;
androidDeviceBrowser: BrowserContext;
};
type TestFixtures = {
createUserDataDir: () => Promise<string>;
Expand Down Expand Up @@ -157,6 +159,27 @@ fixtures.testParametersPathSegment.override(async ({ browserName }, run) => {
await run(browserName);
});

fixtures.androidDevice.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');
device.setDefaultTimeout(120000);
await runTest(device);
await device.close();
}, { scope: 'worker' });

fixtures.androidDeviceBrowser.init(async ({ androidDevice }, runTest) => {
await runTest(await androidDevice.launchBrowser());
}, { scope: 'worker' });

if (process.env.PW_ANDROID_TESTS) {
fixtures.page.override(async ({ androidDeviceBrowser }, run) => {
for (const page of androidDeviceBrowser.pages())
await page.close();
run(await androidDeviceBrowser.newPage());
});
}

export const folio = fixtures.build();

folio.generateParametrizedTests(
Expand Down
Loading

0 comments on commit ad5c028

Please sign in to comment.