From a88d2dc2992ee049b89a8bf4a328661ab73f71cf Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 11 Mar 2021 17:33:40 -0800 Subject: [PATCH] chore: organize per-browser dependencies --- .github/workflows/tests.yml | 18 +- src/cli/cli.ts | 35 +++- src/install/installDeps.ts | 52 +++++ src/nativeDeps.ts | 231 ++++++++++++++++++++++ src/server/validateDependencies.ts | 28 +-- test/cli/cli-codegen-csharp.spec.ts | 8 +- test/cli/cli-codegen-java.spec.ts | 8 +- test/cli/cli-codegen-javascript.spec.ts | 8 +- test/cli/cli-codegen-python-async.spec.ts | 8 +- test/cli/cli-codegen-python.spec.ts | 8 +- utils/docker/Dockerfile.bionic | 148 +++++++++----- utils/docker/Dockerfile.focal | 147 +++++++++----- utils/docker/updateDockerDeps.js | 37 ++++ 13 files changed, 602 insertions(+), 134 deletions(-) create mode 100644 src/install/installDeps.ts create mode 100644 src/nativeDeps.ts create mode 100644 utils/docker/updateDockerDeps.js diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 99169720ac233..2e73d086a0685 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,9 +29,9 @@ jobs: - uses: actions/setup-node@v1 with: node-version: 10 - - uses: microsoft/playwright-github-action@v1 - run: npm ci - run: npm run build + - run: node lib/cli/cli install-deps ${{ matrix.browser }} chromium - run: mkdir -p coredumps # Set core dump file name pattern - run: sudo bash -c 'echo "$(pwd -P)/coredumps/core-pid_%p.dump" > /proc/sys/kernel/core_pattern' @@ -64,9 +64,9 @@ jobs: - uses: actions/setup-node@v1 with: node-version: 10 - - uses: microsoft/playwright-github-action@v1 - run: npm ci - run: npm run build + - run: node lib/cli/cli install-deps ${{ matrix.browser }} chromium - run: npx folio test/ --workers=1 --forbid-only --global-timeout=5400000 --retries=3 --reporter=dot,json --shard=${{ matrix.shard }}/2 env: BROWSER: ${{ matrix.browser }} @@ -94,9 +94,9 @@ jobs: - uses: actions/setup-node@v1 with: node-version: 10 - - uses: microsoft/playwright-github-action@v1 - run: npm ci - run: npm run build + - run: node lib/cli/cli install-deps - run: npx folio test/ --workers=1 --forbid-only --global-timeout=5400000 --retries=3 --reporter=dot,json shell: bash env: @@ -125,9 +125,9 @@ jobs: - uses: actions/setup-node@v1 with: node-version: ${{ matrix.node_version }} - - uses: microsoft/playwright-github-action@v1 - run: npm ci - run: npm run build + - run: node lib/cli/cli install-deps - run: bash packages/installation-tests/installation-tests.sh headful_linux: @@ -142,9 +142,9 @@ jobs: - uses: actions/setup-node@v1 with: node-version: 10 - - uses: microsoft/playwright-github-action@v1 - run: npm ci - run: npm run build + - run: node lib/cli/cli install-deps ${{ matrix.browser }} chromium - run: mkdir -p coredumps # Set core dump file name pattern - run: sudo bash -c 'echo "$(pwd -P)/coredumps/core-pid_%p.dump" > /proc/sys/kernel/core_pattern' @@ -177,9 +177,9 @@ jobs: - uses: actions/setup-node@v1 with: node-version: 10 - - uses: microsoft/playwright-github-action@v1 - run: npm ci - run: npm run build + - run: node lib/cli/cli install-deps chromium - run: mkdir -p coredumps # Set core dump file name pattern - run: sudo bash -c 'echo "$(pwd -P)/coredumps/core-pid_%p.dump" > /proc/sys/kernel/core_pattern' @@ -211,9 +211,9 @@ jobs: - uses: actions/setup-node@v1 with: node-version: 10 - - uses: microsoft/playwright-github-action@v1 - run: npm ci - run: npm run build + - run: node lib/cli/cli install-deps ${{ matrix.browser }} chromium - run: mkdir -p coredumps # Set core dump file name pattern - run: sudo bash -c 'echo "$(pwd -P)/coredumps/core-pid_%p.dump" > /proc/sys/kernel/core_pattern' @@ -240,9 +240,9 @@ jobs: - uses: actions/setup-node@v1 with: node-version: 14 - - uses: microsoft/playwright-github-action@v1 - run: npm ci - run: npm run build + - run: node lib/cli/cli install-deps - name: Create Android Emulator run: utils/avd_recreate.sh - name: Start Android Emulator @@ -269,11 +269,11 @@ jobs: - uses: actions/setup-node@v1 with: node-version: 10 - - uses: microsoft/playwright-github-action@v1 - name: Install Chrome Stable run: sudo apt install google-chrome-stable - run: npm ci - run: npm run build + - run: node lib/cli/cli install-deps chromium - run: mkdir -p coredumps # Set core dump file name pattern - run: sudo bash -c 'echo "$(pwd -P)/coredumps/core-pid_%p.dump" > /proc/sys/kernel/core_pattern' diff --git a/src/cli/cli.ts b/src/cli/cli.ts index 866741e97ee71..3d99a8da8ee53 100755 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -31,6 +31,7 @@ import { Page } from '../client/page'; import { BrowserType } from '../client/browserType'; import { BrowserContextOptions, LaunchOptions } from '../client/types'; import { spawn } from 'child_process'; +import { installDeps } from '../install/installDeps'; program .version('Version ' + require('../../package.json').version) @@ -82,20 +83,34 @@ program program .command('install [browserType...]') .description('ensure browsers necessary for this version of Playwright are installed') - .action(function(browserType) { - const allBrowsers = new Set(['chromium', 'firefox', 'webkit']); - for (const type of browserType) { - if (!allBrowsers.has(type)) { - console.log(`Invalid browser name: '${type}'. Expecting 'chromium', 'firefox' or 'webkit'.`); - process.exit(1); + .action(async function(browserType) { + try { + const allBrowsers = new Set(['chromium', 'firefox', 'webkit']); + for (const type of browserType) { + if (!allBrowsers.has(type)) { + console.log(`Invalid browser name: '${type}'. Expecting 'chromium', 'firefox' or 'webkit'.`); + process.exit(1); + } } + if (browserType.length && browserType.includes('chromium')) + browserType = browserType.concat('ffmpeg'); + await installBrowsers(browserType.length ? browserType : undefined); + } catch (e) { + console.log(`Failed to install browsers\n${e}`); + process.exit(1); } - if (browserType.length && browserType.includes('chromium')) - browserType = browserType.concat('ffmpeg'); - installBrowsers(browserType.length ? browserType : undefined).catch((e: any) => { + }); + +program + .command('install-deps [browserType...]') + .description('install dependencies necessary to run browser') + .action(async function(browserType) { + try { + await installDeps(browserType); + } catch (e) { console.log(`Failed to install browsers\n${e}`); process.exit(1); - }); + } }); const browsers = [ diff --git a/src/install/installDeps.ts b/src/install/installDeps.ts new file mode 100644 index 0000000000000..7bf2db94b6096 --- /dev/null +++ b/src/install/installDeps.ts @@ -0,0 +1,52 @@ +/** + * 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 childProcess from 'child_process'; +import os from 'os'; +import { getUbuntuVersion } from '../utils/ubuntuVersion'; + +const { deps } = require('../nativeDeps'); + +export async function installDeps(browserTypes: string[]) { + if (os.platform() !== 'linux') + return; + if (!browserTypes.length) + browserTypes = ['chromium', 'firefox', 'webkit']; + browserTypes.push('tools'); + + const ubuntuVersion = await getUbuntuVersion(); + if (ubuntuVersion !== '18.04' && ubuntuVersion !== '20.04') { + console.warn('Cannot install dependencies for this linux distribution!'); // eslint-disable-line no-console + return; + } + + const libraries: string[] = []; + for (const browserType of browserTypes) { + if (ubuntuVersion === '18.04') + libraries.push(...deps['bionic'][browserType]); + else if (ubuntuVersion === '20.04') + libraries.push(...deps['focal'][browserType]); + } + const uniqueLibraries = Array.from(new Set(libraries)); + console.log('Installing Ubuntu dependencies...'); // eslint-disable-line no-console + const commands: string[] = []; + commands.push('apt-get update'); + commands.push(['apt-get', 'install', '-y', '--no-install-recommends', + ...uniqueLibraries, + ].join(' ')); + const child = childProcess.spawn('sudo', ['--', 'sh', '-c', `${commands.join('; ')}`], { stdio: 'inherit' }); + await new Promise(f => child.on('exit', f)); +} diff --git a/src/nativeDeps.ts b/src/nativeDeps.ts new file mode 100644 index 0000000000000..e8ab3c4e4acf4 --- /dev/null +++ b/src/nativeDeps.ts @@ -0,0 +1,231 @@ +/** + * 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. + */ + +// This file is used to: +// - Generate Dockerfile.* files +// - Build GitHubAction +// - Execute 'npx playwright install-deps' + +export const deps = { + bionic: { + tools: [ + 'xvfb', + ], + chromium: [ + 'fonts-liberation', + 'libasound2', + 'libatk-bridge2.0-0', + 'libatk1.0-0', + 'libatspi2.0-0', + 'libcairo2', + 'libcups2', + 'libdbus-1-3', + 'libdrm2', + 'libgbm1', + 'libglib2.0-0', + 'libgtk-3-0', + 'libnspr4', + 'libnss3', + 'libpango-1.0-0', + 'libx11-6', + 'libxcb1', + 'libxcomposite1', + 'libxdamage1', + 'libxext6', + 'libxfixes3', + 'libxrandr2', + ], + firefox: [ + 'ffmpeg', + 'libatk1.0-0', + 'libcairo-gobject2', + 'libcairo2', + 'libdbus-1-3', + 'libdbus-glib-1-2', + 'libfontconfig1', + 'libfreetype6', + 'libgdk-pixbuf2.0-0', + 'libglib2.0-0', + 'libgtk-3-0', + 'libpango-1.0-0', + 'libpangocairo-1.0-0', + 'libpangoft2-1.0-0', + 'libx11-6', + 'libx11-xcb1', + 'libxcb-shm0', + 'libxcb1', + 'libxcomposite1', + 'libxcursor1', + 'libxdamage1', + 'libxext6', + 'libxfixes3', + 'libxi6', + 'libxrender1', + 'libxt6', + ], + webkit: [ + 'gstreamer1.0-libav', + 'gstreamer1.0-plugins-bad', + 'gstreamer1.0-plugins-base', + 'gstreamer1.0-plugins-good', + 'libatk-bridge2.0-0', + 'libatk1.0-0', + 'libbrotli1', + 'libcairo2', + 'libegl1', + 'libenchant1c2a', + 'libepoxy0', + 'libfontconfig1', + 'libfreetype6', + 'libgdk-pixbuf2.0-0', + 'libgl1', + 'libgles2', + 'libglib2.0-0', + 'libgstreamer-gl1.0-0', + 'libgstreamer1.0-0', + 'libgtk-3-0', + 'libharfbuzz-icu0', + 'libharfbuzz0b', + 'libhyphen0', + 'libicu60', + 'libjpeg-turbo8', + 'libnotify4', + 'libopenjp2-7', + 'libopus0', + 'libpango-1.0-0', + 'libpng16-16', + 'libsecret-1-0', + 'libvpx5', + 'libwayland-client0', + 'libwayland-egl1', + 'libwayland-server0', + 'libwebp6', + 'libwebpdemux2', + 'libwoff1', + 'libx11-6', + 'libxcomposite1', + 'libxdamage1', + 'libxkbcommon0', + 'libxml2', + 'libxslt1.1', + ], + }, + + focal: { + tools: [ + 'xvfb', + ], + chromium: [ + 'fonts-liberation', + 'libasound2', + 'libatk-bridge2.0-0', + 'libatk1.0-0', + 'libatspi2.0-0', + 'libcairo2', + 'libcups2', + 'libdbus-1-3', + 'libdrm2', + 'libgbm1', + 'libglib2.0-0', + 'libgtk-3-0', + 'libnspr4', + 'libnss3', + 'libpango-1.0-0', + 'libx11-6', + 'libxcb1', + 'libxcomposite1', + 'libxdamage1', + 'libxext6', + 'libxfixes3', + 'libxrandr2', + ], + firefox: [ + 'ffmpeg', + 'libatk1.0-0', + 'libcairo-gobject2', + 'libcairo2', + 'libdbus-1-3', + 'libdbus-glib-1-2', + 'libfontconfig1', + 'libfreetype6', + 'libgdk-pixbuf2.0-0', + 'libglib2.0-0', + 'libgtk-3-0', + 'libpango-1.0-0', + 'libpangocairo-1.0-0', + 'libpangoft2-1.0-0', + 'libx11-6', + 'libx11-xcb1', + 'libxcb-shm0', + 'libxcb1', + 'libxcomposite1', + 'libxcursor1', + 'libxdamage1', + 'libxext6', + 'libxfixes3', + 'libxi6', + 'libxrender1', + 'libxt6', + ], + webkit: [ + 'gstreamer1.0-libav', + 'gstreamer1.0-plugins-bad', + 'gstreamer1.0-plugins-base', + 'gstreamer1.0-plugins-good', + 'libatk-bridge2.0-0', + 'libatk1.0-0', + 'libcairo2', + 'libegl1', + 'libenchant1c2a', + 'libepoxy0', + 'libfontconfig1', + 'libfreetype6', + 'libgdk-pixbuf2.0-0', + 'libgl1', + 'libgles2', + 'libglib2.0-0', + 'libgstreamer-gl1.0-0', + 'libgstreamer1.0-0', + 'libgtk-3-0', + 'libharfbuzz-icu0', + 'libharfbuzz0b', + 'libhyphen0', + 'libicu66', + 'libjpeg-turbo8', + 'libnotify4', + 'libopenjp2-7', + 'libopus0', + 'libpango-1.0-0', + 'libpng16-16', + 'libsecret-1-0', + 'libsoup2.4-1', + 'libvpx6', + 'libwayland-client0', + 'libwayland-egl1', + 'libwayland-server0', + 'libwebp6', + 'libwebpdemux2', + 'libwoff1', + 'libx11-6', + 'libxcomposite1', + 'libxdamage1', + 'libxkbcommon0', + 'libxml2', + 'libxslt1.1', + ], + }, +}; + diff --git a/src/server/validateDependencies.ts b/src/server/validateDependencies.ts index b48e32305ffd7..44bb9585bc1a9 100644 --- a/src/server/validateDependencies.ts +++ b/src/server/validateDependencies.ts @@ -297,16 +297,16 @@ const LIBRARY_TO_PACKAGE_NAME_UBUNTU_18_04: { [s: string]: string} = { 'libglib-2.0.so.0': 'libglib2.0-0', 'libgmodule-2.0.so.0': 'libglib2.0-0', 'libgobject-2.0.so.0': 'libglib2.0-0', - 'libgstapp-1.0.so.0': 'libgstreamer-plugins-base1.0-0', - 'libgstaudio-1.0.so.0': 'libgstreamer-plugins-base1.0-0', + 'libgstapp-1.0.so.0': 'gstreamer1.0-plugins-base', + 'libgstaudio-1.0.so.0': 'gstreamer1.0-plugins-base', 'libgstbase-1.0.so.0': 'libgstreamer1.0-0', - 'libgstcodecparsers-1.0.so.0': 'libgstreamer-plugins-bad1.0-0', - 'libgstfft-1.0.so.0': 'libgstreamer-plugins-base1.0-0', + 'libgstcodecparsers-1.0.so.0': 'gstreamer1.0-plugins-bad', + 'libgstfft-1.0.so.0': 'gstreamer1.0-plugins-base', 'libgstgl-1.0.so.0': 'libgstreamer-gl1.0-0', - 'libgstpbutils-1.0.so.0': 'libgstreamer-plugins-base1.0-0', + 'libgstpbutils-1.0.so.0': 'gstreamer1.0-plugins-base', 'libgstreamer-1.0.so.0': 'libgstreamer1.0-0', - 'libgsttag-1.0.so.0': 'libgstreamer-plugins-base1.0-0', - 'libgstvideo-1.0.so.0': 'libgstreamer-plugins-base1.0-0', + 'libgsttag-1.0.so.0': 'gstreamer1.0-plugins-base', + 'libgstvideo-1.0.so.0': 'gstreamer1.0-plugins-base', 'libgthread-2.0.so.0': 'libglib2.0-0', 'libgtk-3.so.0': 'libgtk-3-0', 'libgtk-x11-2.0.so.0': 'libgtk2.0-0', @@ -384,16 +384,16 @@ const LIBRARY_TO_PACKAGE_NAME_UBUNTU_20_04: { [s: string]: string} = { 'libglib-2.0.so.0': 'libglib2.0-0', 'libgmodule-2.0.so.0': 'libglib2.0-0', 'libgobject-2.0.so.0': 'libglib2.0-0', - 'libgstapp-1.0.so.0': 'libgstreamer-plugins-base1.0-0', - 'libgstaudio-1.0.so.0': 'libgstreamer-plugins-base1.0-0', + 'libgstapp-1.0.so.0': 'gstreamer1.0-plugins-base', + 'libgstaudio-1.0.so.0': 'gstreamer1.0-plugins-base', 'libgstbase-1.0.so.0': 'libgstreamer1.0-0', - 'libgstcodecparsers-1.0.so.0': 'libgstreamer-plugins-bad1.0-0', - 'libgstfft-1.0.so.0': 'libgstreamer-plugins-base1.0-0', + 'libgstcodecparsers-1.0.so.0': 'gstreamer1.0-plugins-bad', + 'libgstfft-1.0.so.0': 'gstreamer1.0-plugins-base', 'libgstgl-1.0.so.0': 'libgstreamer-gl1.0-0', - 'libgstpbutils-1.0.so.0': 'libgstreamer-plugins-base1.0-0', + 'libgstpbutils-1.0.so.0': 'gstreamer1.0-plugins-base', 'libgstreamer-1.0.so.0': 'libgstreamer1.0-0', - 'libgsttag-1.0.so.0': 'libgstreamer-plugins-base1.0-0', - 'libgstvideo-1.0.so.0': 'libgstreamer-plugins-base1.0-0', + 'libgsttag-1.0.so.0': 'gstreamer1.0-plugins-base', + 'libgstvideo-1.0.so.0': 'gstreamer1.0-plugins-base', 'libgthread-2.0.so.0': 'libglib2.0-0', 'libgtk-3.so.0': 'libgtk-3-0', 'libgtk-x11-2.0.so.0': 'libgtk2.0-0', diff --git a/test/cli/cli-codegen-csharp.spec.ts b/test/cli/cli-codegen-csharp.spec.ts index 1380026c24a48..e96d5ac8232db 100644 --- a/test/cli/cli-codegen-csharp.spec.ts +++ b/test/cli/cli-codegen-csharp.spec.ts @@ -76,7 +76,9 @@ var context = await browser.NewContextAsync( expect(cli.text()).toContain(expectedResult); }); -it('should print the correct context options when using a device', async ({ runCLI }) => { +it('should print the correct context options when using a device', (test, { browserName }) => { + test.skip(browserName !== 'chromium'); +}, async ({ runCLI }) => { const cli = runCLI(['codegen', '--device=Pixel 2', '--target=csharp', emptyHTML]); const expectedResult = `await Playwright.InstallAsync(); using var playwright = await Playwright.CreateAsync(); @@ -86,7 +88,9 @@ var context = await browser.NewContextAsync(playwright.Devices["Pixel 2"]);`; expect(cli.text()).toContain(expectedResult); }); -it('should print the correct context options when using a device and additional options', async ({ runCLI }) => { +it('should print the correct context options when using a device and additional options', (test, {browserName}) => { + test.skip(browserName !== 'webkit'); +}, async ({ runCLI }) => { const cli = runCLI([ 'codegen', '--device=iPhone 11', diff --git a/test/cli/cli-codegen-java.spec.ts b/test/cli/cli-codegen-java.spec.ts index 10807496bb8cc..03ccfd3e290f1 100644 --- a/test/cli/cli-codegen-java.spec.ts +++ b/test/cli/cli-codegen-java.spec.ts @@ -45,7 +45,9 @@ it('should print the correct context options for custom settings', async ({ runC expect(cli.text()).toContain(expectedResult); }); -it('should print the correct context options when using a device', async ({ runCLI }) => { +it('should print the correct context options when using a device', (test, { browserName }) => { + test.skip(browserName !== 'chromium'); +}, async ({ runCLI }) => { const cli = runCLI(['codegen', '--device=Pixel 2', '--target=java', emptyHTML]); const expectedResult = `BrowserContext context = browser.newContext(new Browser.NewContextOptions() .setUserAgent("Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36") @@ -57,7 +59,9 @@ it('should print the correct context options when using a device', async ({ runC expect(cli.text()).toContain(expectedResult); }); -it('should print the correct context options when using a device and additional options', async ({ runCLI }) => { +it('should print the correct context options when using a device and additional options', (test, { browserName }) => { + test.skip(browserName !== 'webkit'); +}, async ({ runCLI }) => { const cli = runCLI(['codegen', '--color-scheme=light', '--device=iPhone 11', '--target=java', emptyHTML]); const expectedResult = `BrowserContext context = browser.newContext(new Browser.NewContextOptions() .setColorScheme(ColorScheme.LIGHT) diff --git a/test/cli/cli-codegen-javascript.spec.ts b/test/cli/cli-codegen-javascript.spec.ts index f830e399a8c88..2a212800d3ef3 100644 --- a/test/cli/cli-codegen-javascript.spec.ts +++ b/test/cli/cli-codegen-javascript.spec.ts @@ -51,7 +51,9 @@ it('should print the correct context options for custom settings', async ({ brow }); -it('should print the correct context options when using a device', async ({ runCLI }) => { +it('should print the correct context options when using a device', (test, { browserName }) => { + test.skip(browserName !== 'chromium'); +}, async ({ runCLI }) => { const cli = runCLI(['codegen', '--device=Pixel 2', emptyHTML]); const expectedResult = `const { chromium, devices } = require('playwright'); @@ -66,7 +68,9 @@ it('should print the correct context options when using a device', async ({ runC expect(cli.text()).toContain(expectedResult); }); -it('should print the correct context options when using a device and additional options', async ({ runCLI }) => { +it('should print the correct context options when using a device and additional options', (test, { browserName }) => { + test.skip(browserName !== 'webkit'); +}, async ({ runCLI }) => { const cli = runCLI(['codegen', '--color-scheme=light', '--device=iPhone 11', emptyHTML]); const expectedResult = `const { webkit, devices } = require('playwright'); diff --git a/test/cli/cli-codegen-python-async.spec.ts b/test/cli/cli-codegen-python-async.spec.ts index cf130a57d6984..f6933ffeda1ea 100644 --- a/test/cli/cli-codegen-python-async.spec.ts +++ b/test/cli/cli-codegen-python-async.spec.ts @@ -46,7 +46,9 @@ async def run(playwright): expect(cli.text()).toContain(expectedResult); }); -it('should print the correct context options when using a device', async ({ runCLI }) => { +it('should print the correct context options when using a device', (test, { browserName }) => { + test.skip(browserName !== 'chromium'); +}, async ({ runCLI }) => { const cli = runCLI(['codegen', '--device=Pixel 2', '--target=python-async', emptyHTML]); const expectedResult = `import asyncio from playwright.async_api import async_playwright @@ -58,7 +60,9 @@ async def run(playwright): expect(cli.text()).toContain(expectedResult); }); -it('should print the correct context options when using a device and additional options', async ({ runCLI }) => { +it('should print the correct context options when using a device and additional options', (test, { browserName }) => { + test.skip(browserName !== 'webkit'); +}, async ({ runCLI }) => { const cli = runCLI(['codegen', '--color-scheme=light', '--device=iPhone 11', '--target=python-async', emptyHTML]); const expectedResult = `import asyncio from playwright.async_api import async_playwright diff --git a/test/cli/cli-codegen-python.spec.ts b/test/cli/cli-codegen-python.spec.ts index 4bdc356ec06e9..4671c5d26ac96 100644 --- a/test/cli/cli-codegen-python.spec.ts +++ b/test/cli/cli-codegen-python.spec.ts @@ -44,7 +44,9 @@ def run(playwright): expect(cli.text()).toContain(expectedResult); }); -it('should print the correct context options when using a device', async ({ runCLI }) => { +it('should print the correct context options when using a device', (test, { browserName }) => { + test.skip(browserName !== 'chromium'); +}, async ({ runCLI }) => { const cli = runCLI(['codegen', '--device=Pixel 2', '--target=python', emptyHTML]); const expectedResult = `from playwright.sync_api import sync_playwright @@ -55,7 +57,9 @@ def run(playwright): expect(cli.text()).toContain(expectedResult); }); -it('should print the correct context options when using a device and additional options', async ({ runCLI }) => { +it('should print the correct context options when using a device and additional options', (test, { browserName }) => { + test.skip(browserName !== 'webkit'); +}, async ({ runCLI }) => { const cli = runCLI(['codegen', '--color-scheme=light', '--device=iPhone 11', '--target=python', emptyHTML]); const expectedResult = `from playwright.sync_api import sync_playwright diff --git a/utils/docker/Dockerfile.bionic b/utils/docker/Dockerfile.bionic index 6fa91043a3258..9c1da7a90f2c5 100644 --- a/utils/docker/Dockerfile.bionic +++ b/utils/docker/Dockerfile.bionic @@ -1,59 +1,115 @@ FROM ubuntu:bionic -# === INSTALL BROWSER DEPENDENCIES === +# === GENERATED BROWSER DEPENDENCIES === -# Install WebKit dependencies -RUN apt-get update && apt-get install -y --no-install-recommends \ - libwoff1 \ - libopus0 \ - libwebp6 \ - libwebpdemux2 \ - libenchant1c2a \ - libgudev-1.0-0 \ - libsecret-1-0 \ - libhyphen0 \ - libgdk-pixbuf2.0-0 \ - libegl1 \ - libnotify4 \ - libxslt1.1 \ - libevent-2.1-6 \ - libgles2 \ - libvpx5 \ - libxcomposite1 \ - libatk1.0-0 \ - libatk-bridge2.0-0 \ - libepoxy0 \ - libgtk-3-0 \ - libharfbuzz-icu0 - -# Install gstreamer and plugins to support video playback in WebKit. +# (generated with ./updateDockerDeps.js) + +# tools RUN apt-get update && apt-get install -y --no-install-recommends \ - libgstreamer-gl1.0-0 \ - libgstreamer-plugins-bad1.0-0 \ - gstreamer1.0-plugins-good \ - gstreamer1.0-libav + xvfb -# Install Chromium dependencies +# chromium RUN apt-get update && apt-get install -y --no-install-recommends \ - fonts-liberation \ - libnss3 \ - libxss1 \ - libasound2 \ - fonts-noto-color-emoji \ - libxtst6 - -# Install Firefox dependencies + fonts-liberation\ + libasound2\ + libatk-bridge2.0-0\ + libatk1.0-0\ + libatspi2.0-0\ + libcairo2\ + libcups2\ + libdbus-1-3\ + libdrm2\ + libgbm1\ + libglib2.0-0\ + libgtk-3-0\ + libnspr4\ + libnss3\ + libpango-1.0-0\ + libx11-6\ + libxcb1\ + libxcomposite1\ + libxdamage1\ + libxext6\ + libxfixes3\ + libxrandr2 + +# firefox RUN apt-get update && apt-get install -y --no-install-recommends \ - libdbus-glib-1-2 \ + ffmpeg\ + libatk1.0-0\ + libcairo-gobject2\ + libcairo2\ + libdbus-1-3\ + libdbus-glib-1-2\ + libfontconfig1\ + libfreetype6\ + libgdk-pixbuf2.0-0\ + libglib2.0-0\ + libgtk-3-0\ + libpango-1.0-0\ + libpangocairo-1.0-0\ + libpangoft2-1.0-0\ + libx11-6\ + libx11-xcb1\ + libxcb-shm0\ + libxcb1\ + libxcomposite1\ + libxcursor1\ + libxdamage1\ + libxext6\ + libxfixes3\ + libxi6\ + libxrender1\ libxt6 -# Install ffmpeg to bring in audio and video codecs necessary for playing videos in Firefox. +# webkit RUN apt-get update && apt-get install -y --no-install-recommends \ - ffmpeg - -# (Optional) Install XVFB if there's a need to run browsers in headful mode -RUN apt-get update && apt-get install -y --no-install-recommends \ - xvfb + gstreamer1.0-libav\ + gstreamer1.0-plugins-bad\ + gstreamer1.0-plugins-base\ + gstreamer1.0-plugins-good\ + libatk-bridge2.0-0\ + libatk1.0-0\ + libbrotli1\ + libcairo2\ + libegl1\ + libenchant1c2a\ + libepoxy0\ + libfontconfig1\ + libfreetype6\ + libgdk-pixbuf2.0-0\ + libgl1\ + libgles2\ + libglib2.0-0\ + libgstreamer-gl1.0-0\ + libgstreamer1.0-0\ + libgtk-3-0\ + libharfbuzz-icu0\ + libharfbuzz0b\ + libhyphen0\ + libicu60\ + libjpeg-turbo8\ + libnotify4\ + libopenjp2-7\ + libopus0\ + libpango-1.0-0\ + libpng16-16\ + libsecret-1-0\ + libvpx5\ + libwayland-client0\ + libwayland-egl1\ + libwayland-server0\ + libwebp6\ + libwebpdemux2\ + libwoff1\ + libx11-6\ + libxcomposite1\ + libxdamage1\ + libxkbcommon0\ + libxml2\ + libxslt1.1 + +# === GENERATED BROWSER DEPENDENCIES END === # === INSTALL Node.js === diff --git a/utils/docker/Dockerfile.focal b/utils/docker/Dockerfile.focal index 795b9a12cae20..4c387a9bb196e 100644 --- a/utils/docker/Dockerfile.focal +++ b/utils/docker/Dockerfile.focal @@ -1,58 +1,115 @@ FROM ubuntu:focal -# === INSTALL BROWSER DEPENDENCIES === +# === GENERATED BROWSER DEPENDENCIES === -# Install WebKit dependencies -RUN apt-get update && apt-get install -y --no-install-recommends \ - libwoff1 \ - libopus0 \ - libwebp6 \ - libwebpdemux2 \ - libenchant1c2a \ - libgudev-1.0-0 \ - libsecret-1-0 \ - libhyphen0 \ - libgdk-pixbuf2.0-0 \ - libegl1 \ - libnotify4 \ - libxslt1.1 \ - libevent-2.1-7 \ - libgles2 \ - libxcomposite1 \ - libatk1.0-0 \ - libatk-bridge2.0-0 \ - libepoxy0 \ - libgtk-3-0 \ - libharfbuzz-icu0 - -# Install gstreamer and plugins to support video playback in WebKit. +# (generated with ./updateDockerDeps.js) + +# tools RUN apt-get update && apt-get install -y --no-install-recommends \ - libgstreamer-gl1.0-0 \ - libgstreamer-plugins-bad1.0-0 \ - gstreamer1.0-plugins-good \ - gstreamer1.0-libav + xvfb -# Install Chromium dependencies +# chromium RUN apt-get update && apt-get install -y --no-install-recommends \ - fonts-liberation \ - libnss3 \ - libxss1 \ - libasound2 \ - fonts-noto-color-emoji \ - libxtst6 - -# Install Firefox dependencies + fonts-liberation\ + libasound2\ + libatk-bridge2.0-0\ + libatk1.0-0\ + libatspi2.0-0\ + libcairo2\ + libcups2\ + libdbus-1-3\ + libdrm2\ + libgbm1\ + libglib2.0-0\ + libgtk-3-0\ + libnspr4\ + libnss3\ + libpango-1.0-0\ + libx11-6\ + libxcb1\ + libxcomposite1\ + libxdamage1\ + libxext6\ + libxfixes3\ + libxrandr2 + +# firefox RUN apt-get update && apt-get install -y --no-install-recommends \ - libdbus-glib-1-2 \ + ffmpeg\ + libatk1.0-0\ + libcairo-gobject2\ + libcairo2\ + libdbus-1-3\ + libdbus-glib-1-2\ + libfontconfig1\ + libfreetype6\ + libgdk-pixbuf2.0-0\ + libglib2.0-0\ + libgtk-3-0\ + libpango-1.0-0\ + libpangocairo-1.0-0\ + libpangoft2-1.0-0\ + libx11-6\ + libx11-xcb1\ + libxcb-shm0\ + libxcb1\ + libxcomposite1\ + libxcursor1\ + libxdamage1\ + libxext6\ + libxfixes3\ + libxi6\ + libxrender1\ libxt6 -# Install ffmpeg to bring in audio and video codecs necessary for playing videos in Firefox. +# webkit RUN apt-get update && apt-get install -y --no-install-recommends \ - ffmpeg - -# (Optional) Install XVFB if there's a need to run browsers in headful mode -RUN apt-get update && apt-get install -y --no-install-recommends \ - xvfb + gstreamer1.0-libav\ + gstreamer1.0-plugins-bad\ + gstreamer1.0-plugins-base\ + gstreamer1.0-plugins-good\ + libatk-bridge2.0-0\ + libatk1.0-0\ + libcairo2\ + libegl1\ + libenchant1c2a\ + libepoxy0\ + libfontconfig1\ + libfreetype6\ + libgdk-pixbuf2.0-0\ + libgl1\ + libgles2\ + libglib2.0-0\ + libgstreamer-gl1.0-0\ + libgstreamer1.0-0\ + libgtk-3-0\ + libharfbuzz-icu0\ + libharfbuzz0b\ + libhyphen0\ + libicu66\ + libjpeg-turbo8\ + libnotify4\ + libopenjp2-7\ + libopus0\ + libpango-1.0-0\ + libpng16-16\ + libsecret-1-0\ + libsoup2.4-1\ + libvpx6\ + libwayland-client0\ + libwayland-egl1\ + libwayland-server0\ + libwebp6\ + libwebpdemux2\ + libwoff1\ + libx11-6\ + libxcomposite1\ + libxdamage1\ + libxkbcommon0\ + libxml2\ + libxslt1.1 + +# === GENERATED BROWSER DEPENDENCIES END === # === INSTALL Node.js === diff --git a/utils/docker/updateDockerDeps.js b/utils/docker/updateDockerDeps.js new file mode 100644 index 0000000000000..14d28cc7983e7 --- /dev/null +++ b/utils/docker/updateDockerDeps.js @@ -0,0 +1,37 @@ +/** + * 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 fs = require('fs'); + +const { deps } = require('../../lib/nativeDeps'); +for (const distro in deps) { + const file = fs.readFileSync(require.resolve(`./Dockerfile.${distro}`), 'utf-8'); + const newContent = []; + newContent.push('# === GENERATED BROWSER DEPENDENCIES ==='); + newContent.push(''); + newContent.push('# (generated with ./updateDockerDeps.js)'); + for (const browser in deps[distro]) { + newContent.push(''); + newContent.push(`# ${browser}`); + newContent.push(`RUN apt-get update && apt-get install -y --no-install-recommends \\`); + newContent.push(' ' + deps[distro][browser].join('\\\n ')); + } + newContent.push(''); + newContent.push('# === GENERATED BROWSER DEPENDENCIES END ==='); + const result = file.replace(/# === GENERATED BROWSER DEPENDENCIES ===[.\s\S]*# === GENERATED BROWSER DEPENDENCIES END ===/g, newContent.join('\n')); + console.log(`Updating Dockerfile.${distro}`); + fs.writeFileSync(require.resolve(`./Dockerfile.${distro}`), result); +}