diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 32a49ddef5..00b58daa98 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -316,6 +316,86 @@ jobs: name: chrome-stable-mac-test-results path: test-results + firefox_stable_linux: + name: "Firefox Stable (Linux)" + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 10 + - run: npm ci + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + - run: npm run build + - run: node lib/cli/cli install-deps firefox + - run: node lib/cli/cli install ffmpeg firefox-stable chromium + # XVFB-RUN merges both STDOUT and STDERR, whereas we need only STDERR + # Wrap `npm run` in a subshell to redirect STDERR to file. + - run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- bash -c "npm run ftest" + env: + PWTEST_CHANNEL: "firefox-stable" + - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json + if: always() + - uses: actions/upload-artifact@v1 + if: ${{ always() }} + with: + name: firefox-stable-linux-test-results + path: test-results + + firefox_stable_win: + name: "Firefox Stable (Win)" + runs-on: windows-latest + steps: + - name: Install Media Pack + shell: powershell + run: Install-WindowsFeature Server-Media-Foundation + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 10 + - run: npm ci + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + - run: npm run build + - run: node lib/cli/cli install ffmpeg firefox-stable chromium + - run: npm run ftest + shell: bash + env: + PWTEST_CHANNEL: "firefox-stable" + - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json + if: always() + shell: bash + - uses: actions/upload-artifact@v1 + if: ${{ always() }} + with: + name: firefox-stable-win-test-results + path: test-results + + firefox_stable_mac: + name: "Firefox Stable (Mac)" + runs-on: macos-10.15 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 10 + - run: npm ci + env: + PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 + - run: npm run build + - run: node lib/cli/cli install ffmpeg firefox-stable chromium + - run: npm run ftest + env: + PWTEST_CHANNEL: "firefox-stable" + - run: ./utils/upload_flakiness_dashboard.sh ./test-results/report.json + if: always() + - uses: actions/upload-artifact@v1 + if: ${{ always() }} + with: + name: firefox-stable-mac-test-results + path: test-results + edge_stable_win: name: "Edge Stable (Win)" runs-on: windows-latest diff --git a/browsers.json b/browsers.json index b7545e16ad..54a19360ac 100644 --- a/browsers.json +++ b/browsers.json @@ -11,6 +11,11 @@ "revision": "1245", "installByDefault": true }, + { + "name": "firefox-stable", + "revision": "1242", + "installByDefault": false + }, { "name": "webkit", "revision": "1463", diff --git a/src/cli/cli.ts b/src/cli/cli.ts index 21b6306b61..0b37a54309 100755 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -84,18 +84,18 @@ program program .command('install [browserType...]') .description('ensure browsers necessary for this version of Playwright are installed') - .action(async function(browserType) { + .action(async function(browserTypes) { try { const allBrowsers = new Set(allBrowserNames); - for (const type of browserType) { - if (!allBrowsers.has(type)) { - console.log(`Invalid browser name: '${type}'. Expecting one of: ${allBrowserNames.map(name => `'${name}'`).join(', ')}`); + for (const browserType of browserTypes) { + if (!allBrowsers.has(browserType)) { + console.log(`Invalid browser name: '${browserType}'. Expecting one of: ${allBrowserNames.map(name => `'${name}'`).join(', ')}`); process.exit(1); } } - if (browserType.length && browserType.includes('chromium')) - browserType = browserType.concat('ffmpeg'); - await installBrowsers(browserType.length ? browserType : undefined); + if (browserTypes.length && browserTypes.includes('chromium')) + browserTypes = browserTypes.concat('ffmpeg'); + await installBrowsers(browserTypes.length ? browserTypes : undefined); } catch (e) { console.log(`Failed to install browsers\n${e}`); process.exit(1); diff --git a/src/protocol/channels.ts b/src/protocol/channels.ts index 1f1932424c..d6980d2f2d 100644 --- a/src/protocol/channels.ts +++ b/src/protocol/channels.ts @@ -208,7 +208,7 @@ export interface BrowserTypeChannel extends Channel { connectOverCDP(params: BrowserTypeConnectOverCDPParams, metadata?: Metadata): Promise; } export type BrowserTypeLaunchParams = { - channel?: 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary', + channel?: 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary' | 'firefox-stable', executablePath?: string, args?: string[], ignoreAllDefaultArgs?: boolean, @@ -232,7 +232,7 @@ export type BrowserTypeLaunchParams = { slowMo?: number, }; export type BrowserTypeLaunchOptions = { - channel?: 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary', + channel?: 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary' | 'firefox-stable', executablePath?: string, args?: string[], ignoreAllDefaultArgs?: boolean, @@ -259,7 +259,7 @@ export type BrowserTypeLaunchResult = { browser: BrowserChannel, }; export type BrowserTypeLaunchPersistentContextParams = { - channel?: 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary', + channel?: 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary' | 'firefox-stable', executablePath?: string, args?: string[], ignoreAllDefaultArgs?: boolean, @@ -329,7 +329,7 @@ export type BrowserTypeLaunchPersistentContextParams = { slowMo?: number, }; export type BrowserTypeLaunchPersistentContextOptions = { - channel?: 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary', + channel?: 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary' | 'firefox-stable', executablePath?: string, args?: string[], ignoreAllDefaultArgs?: boolean, diff --git a/src/protocol/protocol.yml b/src/protocol/protocol.yml index 4beb3a4c76..ef766a9f5e 100644 --- a/src/protocol/protocol.yml +++ b/src/protocol/protocol.yml @@ -237,6 +237,7 @@ LaunchOptions: - msedge-beta - msedge-dev - msedge-canary + - firefox-stable executablePath: string? args: type: array? diff --git a/src/protocol/validator.ts b/src/protocol/validator.ts index 4a47567f73..9194d0c1eb 100644 --- a/src/protocol/validator.ts +++ b/src/protocol/validator.ts @@ -154,7 +154,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme { contentScript: tOptional(tBoolean), }); scheme.BrowserTypeLaunchParams = tObject({ - channel: tOptional(tEnum(['chrome', 'chrome-beta', 'chrome-dev', 'chrome-canary', 'msedge', 'msedge-beta', 'msedge-dev', 'msedge-canary'])), + channel: tOptional(tEnum(['chrome', 'chrome-beta', 'chrome-dev', 'chrome-canary', 'msedge', 'msedge-beta', 'msedge-dev', 'msedge-canary', 'firefox-stable'])), executablePath: tOptional(tString), args: tOptional(tArray(tString)), ignoreAllDefaultArgs: tOptional(tBoolean), @@ -178,7 +178,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme { slowMo: tOptional(tNumber), }); scheme.BrowserTypeLaunchPersistentContextParams = tObject({ - channel: tOptional(tEnum(['chrome', 'chrome-beta', 'chrome-dev', 'chrome-canary', 'msedge', 'msedge-beta', 'msedge-dev', 'msedge-canary'])), + channel: tOptional(tEnum(['chrome', 'chrome-beta', 'chrome-dev', 'chrome-canary', 'msedge', 'msedge-beta', 'msedge-dev', 'msedge-canary', 'firefox-stable'])), executablePath: tOptional(tString), args: tOptional(tArray(tString)), ignoreAllDefaultArgs: tOptional(tBoolean), diff --git a/src/server/firefox/firefox.ts b/src/server/firefox/firefox.ts index fc6a79e24e..d172a06adc 100644 --- a/src/server/firefox/firefox.ts +++ b/src/server/firefox/firefox.ts @@ -18,6 +18,7 @@ import * as os from 'os'; import fs from 'fs'; import path from 'path'; +import { assert } from '../../utils/utils'; import { FFBrowser } from './ffBrowser'; import { kBrowserCloseMessageId } from './ffConnection'; import { BrowserType } from '../browserType'; @@ -31,6 +32,18 @@ export class Firefox extends BrowserType { super('firefox', playwrightOptions); } + executablePath(channel?: types.BrowserChannel): string { + if (channel) { + let executablePath = undefined; + if ((channel as any) === 'firefox-stable') + executablePath = this._registry.executablePath('firefox-stable'); + assert(executablePath, `unsupported firefox channel "${channel}"`); + assert(fs.existsSync(executablePath), `"${channel}" channel is not installed. Try running 'npx playwright install ${channel}'`); + return executablePath; + } + return super.executablePath(channel); + } + _connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise { return FFBrowser.connect(transport, options); } diff --git a/src/server/types.ts b/src/server/types.ts index d362d1f935..67de5365d2 100644 --- a/src/server/types.ts +++ b/src/server/types.ts @@ -252,7 +252,7 @@ export type BrowserContextOptions = { export type EnvArray = { name: string, value: string }[]; -export type BrowserChannel = 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary'; +export type BrowserChannel = 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary' | 'firefox-stable'; type LaunchOptionsBase = { channel?: BrowserChannel, diff --git a/src/server/validateDependencies.ts b/src/server/validateDependencies.ts index c68d94aa72..965fb122f4 100644 --- a/src/server/validateDependencies.ts +++ b/src/server/validateDependencies.ts @@ -47,6 +47,7 @@ const DL_OPEN_LIBRARIES = { 'webkit': ['libGLESv2.so.2', 'libx264.so'], 'webkit-technology-preview': ['libGLESv2.so.2', 'libx264.so'], 'firefox': [], + 'firefox-stable': [], 'clank': [], 'ffmpeg': [], }; diff --git a/src/utils/registry.ts b/src/utils/registry.ts index 4a440178e3..9cf20b6391 100644 --- a/src/utils/registry.ts +++ b/src/utils/registry.ts @@ -22,8 +22,8 @@ import * as util from 'util'; import { getUbuntuVersionSync } from './ubuntuVersion'; import { assert, getFromENV } from './utils'; -export type BrowserName = 'chromium'|'webkit'|'firefox'|'ffmpeg'|'webkit-technology-preview'; -export const allBrowserNames: BrowserName[] = ['chromium', 'webkit', 'firefox', 'ffmpeg', 'webkit-technology-preview']; +export type BrowserName = 'chromium'|'webkit'|'firefox'|'firefox-stable'|'ffmpeg'|'webkit-technology-preview'; +export const allBrowserNames: BrowserName[] = ['chromium', 'webkit', 'firefox', 'ffmpeg', 'webkit-technology-preview', 'firefox-stable']; const PACKAGE_PATH = path.join(__dirname, '..', '..'); @@ -58,6 +58,17 @@ const EXECUTABLE_PATHS = { 'win32': ['firefox', 'firefox.exe'], 'win64': ['firefox', 'firefox.exe'], }, + 'firefox-stable': { + 'ubuntu18.04': ['firefox', 'firefox'], + 'ubuntu20.04': ['firefox', 'firefox'], + 'mac10.13': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'], + 'mac10.14': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'], + 'mac10.15': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'], + 'mac11': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'], + 'mac11-arm64': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'], + 'win32': ['firefox', 'firefox.exe'], + 'win64': ['firefox', 'firefox.exe'], + }, 'webkit': { 'ubuntu18.04': ['pw_run.sh'], 'ubuntu20.04': ['pw_run.sh'], @@ -116,6 +127,17 @@ const DOWNLOAD_URLS = { 'win32': '%s/builds/firefox/%s/firefox-win32.zip', 'win64': '%s/builds/firefox/%s/firefox-win64.zip', }, + 'firefox-stable': { + 'ubuntu18.04': '%s/builds/firefox-stable/%s/firefox-stable-ubuntu-18.04.zip', + 'ubuntu20.04': '%s/builds/firefox-stable/%s/firefox-stable-ubuntu-20.04.zip', + 'mac10.13': '%s/builds/firefox-stable/%s/firefox-stable-mac-10.14.zip', + 'mac10.14': '%s/builds/firefox-stable/%s/firefox-stable-mac-10.14.zip', + 'mac10.15': '%s/builds/firefox-stable/%s/firefox-stable-mac-10.14.zip', + 'mac11': '%s/builds/firefox-stable/%s/firefox-stable-mac-10.14.zip', + 'mac11-arm64': '%s/builds/firefox-stable/%s/firefox-stable-mac-11.0-arm64.zip', + 'win32': '%s/builds/firefox-stable/%s/firefox-stable-win32.zip', + 'win64': '%s/builds/firefox-stable/%s/firefox-stable-win64.zip', + }, 'webkit': { 'ubuntu18.04': '%s/builds/webkit/%s/webkit-ubuntu-18.04.zip', 'ubuntu20.04': '%s/builds/webkit/%s/webkit-ubuntu-20.04.zip', @@ -310,6 +332,7 @@ export class Registry { const envDownloadHost: { [key: string]: string } = { 'chromium': 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST', 'firefox': 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST', + 'firefox-stable': 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST', 'webkit': 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST', 'webkit-technology-preview': 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST', 'ffmpeg': 'PLAYWRIGHT_FFMPEG_DOWNLOAD_HOST', diff --git a/tests/beforeunload.spec.ts b/tests/beforeunload.spec.ts index 3f7aff04b7..f66247001a 100644 --- a/tests/beforeunload.spec.ts +++ b/tests/beforeunload.spec.ts @@ -61,7 +61,7 @@ it('should run beforeunload if asked for', async ({context, server, isChromium, else if (isWebKit) expect(dialog.message()).toBe('Leave?'); else - expect(dialog.message()).toBe('This page is asking you to confirm that you want to leave — information you’ve entered may not be saved.'); + expect(dialog.message()).toContain('This page is asking you to confirm that you want to leave'); await Promise.all([ dialog.accept(), newPage.waitForEvent('close'),