test: android test enhancements (#15797)

This commit is contained in:
Max Schmitt 2022-07-20 18:27:08 +02:00 коммит произвёл GitHub
Родитель 35a7be24a3
Коммит 501b24a078
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
10 изменённых файлов: 49 добавлений и 75 удалений

3
.github/workflows/tests_android.yml поставляемый
Просмотреть файл

@ -11,7 +11,7 @@ on:
- release-*
paths:
- "**android**"
- "utils/avd_*.js"
- "utils/avd_*"
- ".github/workflows/tests_android.yml"
env:
@ -38,7 +38,6 @@ jobs:
env:
DEBUG: pw:install
- run: npm run build
- run: npx playwright install-deps
- name: Create Android Emulator
run: utils/avd_recreate.sh
- name: Start Android Emulator

Просмотреть файл

@ -17,6 +17,10 @@
import net from 'net';
import { androidTest as test, expect } from './androidTest';
test.afterAll(async ({ androidDevice }) => {
await androidDevice.shell('am force-stop com.android.chrome');
});
test('androidDevice.model', async function({ androidDevice }) {
expect(androidDevice.model()).toBe('sdk_gphone64_x86_64');
});
@ -55,6 +59,7 @@ test('should be able to send CDP messages', async ({ androidDevice }) => {
await client.send('Runtime.enable');
const evalResponse = await client.send('Runtime.evaluate', { expression: '1 + 2', returnByValue: true });
expect(evalResponse.result.value).toBe(3);
await context.close();
});
test('should be able to use a custom port', async function({ playwright }) {
@ -102,4 +107,5 @@ test('should be able to pass context options', async ({ androidDevice, httpsServ
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches)).toBe(true);
expect(await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches)).toBe(false);
await context.close();
});

Просмотреть файл

@ -52,7 +52,7 @@ test('androidDevice.push', async function({ androidDevice }) {
});
test('androidDevice.fill', async function({ androidDevice }) {
test.fixme(!!process.env.CI, 'Hangs on the bots');
test.fixme(true, 'Hangs on the bots');
await androidDevice.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');
await androidDevice.fill({ res: 'org.chromium.webview_shell:id/url_field' }, 'Hello');
@ -81,7 +81,7 @@ test('androidDevice.options.omitDriverInstall', async function({ playwright }) {
const filePath = join(require.resolve('playwright-core'), '..', 'bin', file);
await androidDevice.installApk(await fs.promises.readFile(filePath));
}
androidDevice.shell('am instrument -w com.microsoft.playwright.androiddriver.test/androidx.test.runner.AndroidJUnitRunner').catch(e => console.error);
androidDevice.shell('am instrument -w com.microsoft.playwright.androiddriver.test/androidx.test.runner.AndroidJUnitRunner').catch(e => console.error(e));
// wait for finishing fill operation
while (!fillStatus)

Просмотреть файл

@ -48,7 +48,7 @@ test('should navigate page internally', async function({ androidDevice }) {
});
test('should navigate page externally', async function({ androidDevice }) {
test.fixme(!!process.env.CI, 'Hangs on the bots');
test.fixme(true, 'Hangs on the bots');
expect(androidDevice.webViews().length).toBe(0);
await androidDevice.shell('am start org.chromium.webview_shell/.WebViewBrowserActivity');

Просмотреть файл

@ -202,7 +202,9 @@ it('allInnerTexts should work', async ({ page }) => {
expect(await page.locator('div').allInnerTexts()).toEqual(['A', 'B', 'C']);
});
it('isVisible and isHidden should work with details', async ({ page }) => {
it('isVisible and isHidden should work with details', async ({ page, isAndroid }) => {
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/10674' });
it.skip(isAndroid, 'We can\'t disable the AutoExpandDetailsElement feature on Android');
await page.setContent(`<details>
<summary>click to open</summary>
<ul>

Просмотреть файл

@ -16,16 +16,34 @@
import { test as it, expect } from './pageTest';
import { waitForTestLog } from '../config/utils';
import type { Locator } from 'playwright-core';
type BoundingBox = Awaited<ReturnType<Locator['boundingBox']>>;
it.skip(({ mode }) => mode !== 'default', 'Highlight element has a closed shadow-root on != default');
it('should highlight locator', async ({ page }) => {
it('should highlight locator', async ({ page, isAndroid }) => {
await page.setContent(`<input type='text' />`);
const textPromise = waitForTestLog<string>(page, 'Highlight text for test: ');
const boxPromise = waitForTestLog<{ x: number, y: number, width: number, height: number }>(page, 'Highlight box for test: ');
await page.locator('input').highlight();
expect(await textPromise).toBe('input');
const box1 = await page.locator('input').boundingBox();
const box2 = await boxPromise;
let box1 = await page.locator('input').boundingBox();
let box2 = await boxPromise;
if (isAndroid) {
box1 = roundBox(box1);
box2 = roundBox(box2);
}
expect(box1).toEqual(box2);
});
function roundBox(box: BoundingBox): BoundingBox {
return {
x: Math.round(box.x),
y: Math.round(box.y),
width: Math.round(box.width),
height: Math.round(box.height),
};
}

Просмотреть файл

@ -13,7 +13,8 @@ mkdir ${SDKDIR}/cmdline-tools
echo Downloading Android SDK...
cd ${SDKDIR}/cmdline-tools
COMMAND_LINE_TOOLS_ZIP=${SDKDIR}/commandlinetools.zip
curl https://dl.google.com/android/repository/commandlinetools-mac-7583922_latest.zip -o ${COMMAND_LINE_TOOLS_ZIP}
# https://developer.android.com/studio#command-tools
curl https://dl.google.com/android/repository/commandlinetools-mac-8512546_latest.zip -o ${COMMAND_LINE_TOOLS_ZIP}
unzip ${COMMAND_LINE_TOOLS_ZIP}
rm ${COMMAND_LINE_TOOLS_ZIP}
mv cmdline-tools latest

Просмотреть файл

@ -8,8 +8,7 @@ if [[ -z "${ANDROID_HOME}" ]]; then
export ANDROID_SDK_ROOT=${SDKDIR}
fi
echo "Killing previous emulators"
${ANDROID_HOME}/platform-tools/adb devices | grep emulator | cut -f1 | while read line; do ${ANDROID_HOME}/platform-tools/adb -s $line emu kill; done
bash $PWD/utils/avd_stop.sh
EMULATOR_GPU="host"
if [[ -n "${GITHUB_ACTIONS}" ]]; then

12
utils/avd_stop.sh Executable file
Просмотреть файл

@ -0,0 +1,12 @@
#!/bin/bash
set -e
if [[ -z "${ANDROID_HOME}" ]]; then
SDKDIR=$PWD/.android-sdk
export ANDROID_HOME=${SDKDIR}
export ANDROID_SDK_ROOT=${SDKDIR}
fi
echo "Killing previous emulators"
${ANDROID_HOME}/platform-tools/adb devices | grep emulator | cut -f1 | while read line; do ${ANDROID_HOME}/platform-tools/adb -s $line emu kill; done

Просмотреть файл

@ -1,63 +0,0 @@
/**
* 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.
*/
const { _clank } = require('..');
const assert = require('assert');
const childProcess = require('child_process');
const path = require('path');
const readline = require('readline');
(async () => {
setTimeout(() => {
console.error('Timed out starting emulator');
process.exit(1);
}, 60000);
const proc = childProcess.spawn(path.join(process.cwd(), '.android-sdk/emulator/emulator'), ['-no-window', '-avd', 'android30', '-verbose'], {
env: {
...process.env,
ANDROID_SDK_ROOT: path.join(process.cwd(), '.android-sdk'),
ANDROID_HOME: path.join(process.cwd(), '.android-sdk'),
}
});
proc.stdout.on('data', data => console.log(data.toString()));
proc.stderr.on('data', data => console.log(data.toString()));
await waitForLine(proc, /boot completed/);
const context = await _clank.launchPersistentContext('');
const [page] = context.pages();
await page.goto('data:text/html,<title>Hello world</title>');
assert(await page.title() === 'Hello world');
await context.close();
process.exit(0);
})();
async function waitForLine(proc, regex) {
return new Promise((resolve, reject) => {
const rl = readline.createInterface({ input: proc.stdout });
const failError = new Error('Process failed to launch!');
rl.on('line', onLine);
rl.on('close', reject.bind(null, failError));
proc.on('exit', reject.bind(null, failError));
proc.on('error', reject.bind(null, failError));
function onLine(line) {
const match = line.match(regex);
if (!match)
return;
resolve(match);
}
});
}