diff --git a/.github/workflows/tests_bidi.yml b/.github/workflows/tests_bidi.yml index 433294dbea6a9..b534a7b7474df 100644 --- a/.github/workflows/tests_bidi.yml +++ b/.github/workflows/tests_bidi.yml @@ -26,8 +26,7 @@ jobs: strategy: fail-fast: false matrix: - # TODO: add Firefox - channel: [bidi-chrome-stable] + channel: [bidi-chromium, bidi-firefox-beta] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 @@ -38,5 +37,8 @@ jobs: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' - run: npm run build - run: npx playwright install --with-deps chromium + if: matrix.channel == 'bidi-chromium' + - run: npx -y @puppeteer/browsers install firefox@beta + if: matrix.channel == 'bidi-firefox-beta' - name: Run tests run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run biditest -- --project=${{ matrix.channel }}* diff --git a/packages/playwright-core/src/server/registry/index.ts b/packages/playwright-core/src/server/registry/index.ts index 058e0bcbc34b4..4e942967a48eb 100644 --- a/packages/playwright-core/src/server/registry/index.ts +++ b/packages/playwright-core/src/server/registry/index.ts @@ -354,7 +354,7 @@ function readDescriptors(browsersJSON: BrowsersJSON) { export type BrowserName = 'chromium' | 'firefox' | 'webkit' | 'bidi'; type InternalTool = 'ffmpeg' | 'firefox-beta' | 'chromium-tip-of-tree' | 'android'; -type BidiChannel = 'bidi-firefox-stable' | 'bidi-chrome-canary' | 'bidi-chrome-stable'; +type BidiChannel = 'bidi-firefox-stable' | 'bidi-firefox-beta' | 'bidi-firefox-nightly' | 'bidi-chrome-canary' | 'bidi-chrome-stable' | 'bidi-chromium'; type ChromiumChannel = 'chrome' | 'chrome-beta' | 'chrome-dev' | 'chrome-canary' | 'msedge' | 'msedge-beta' | 'msedge-dev' | 'msedge-canary'; const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-tip-of-tree']; @@ -525,11 +525,22 @@ export class Registry { 'win32': `\\Microsoft\\Edge SxS\\Application\\msedge.exe`, })); - this._executables.push(this._createBidiChannel('bidi-firefox-stable', { - 'linux': '/usr/bin/firefox', - 'darwin': '/Applications/Firefox.app/Contents/MacOS/firefox', - 'win32': '\\Mozilla Firefox\\firefox.exe', + this._executables.push(this._createBidiFirefoxChannel('bidi-firefox-stable', { + 'linux': '/firefox/firefox', + 'darwin': '/Firefox.app/Contents/MacOS/firefox', + 'win32': '\\core\\firefox.exe', })); + this._executables.push(this._createBidiFirefoxChannel('bidi-firefox-beta', { + 'linux': '/firefox/firefox', + 'darwin': '/Firefox.app/Contents/MacOS/firefox', + 'win32': '\\core\\firefox.exe', + })); + this._executables.push(this._createBidiFirefoxChannel('bidi-firefox-nightly', { + 'linux': '/firefox/firefox', + 'darwin': '/Firefox Nightly.app/Contents/MacOS/firefox', + 'win32': '\\firefox\\firefox.exe', + })); + this._executables.push(this._createBidiChannel('bidi-chrome-stable', { 'linux': '/opt/google/chrome/chrome', 'darwin': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', @@ -540,6 +551,21 @@ export class Registry { 'darwin': '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary', 'win32': `\\Google\\Chrome SxS\\Application\\chrome.exe`, })); + this._executables.push({ + type: 'browser', + name: 'bidi-chromium', + browserName: 'bidi', + directory: chromium.dir, + executablePath: () => chromiumExecutable, + executablePathOrDie: (sdkLanguage: string) => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage), + installType: 'download-on-demand', + _validateHostRequirements: (sdkLanguage: string) => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']), + downloadURLs: this._downloadURLs(chromium), + browserVersion: chromium.browserVersion, + _install: () => this._downloadExecutable(chromium, chromiumExecutable), + _dependencyGroup: 'chromium', + _isHermeticInstallation: true, + }); const firefox = descriptors.find(d => d.name === 'firefox')!; const firefoxExecutable = findExecutablePath(firefox.dir, 'firefox'); @@ -691,6 +717,48 @@ export class Registry { }; } + private _createBidiFirefoxChannel(name: BidiChannel, lookAt: Record<'linux' | 'darwin' | 'win32', string>, install?: () => Promise): ExecutableImpl { + const executablePath = (sdkLanguage: string, shouldThrow: boolean) => { + const suffix = lookAt[process.platform as 'linux' | 'darwin' | 'win32']; + if (!suffix) { + if (shouldThrow) + throw new Error(`Firefox distribution '${name}' is not supported on ${process.platform}`); + return undefined; + } + const folder = path.resolve('firefox'); + let channelName = 'stable'; + if (name.includes('beta')) + channelName = 'beta'; + else if (name.includes('nightly')) + channelName = 'nightly'; + const installedVersions = fs.readdirSync(folder); + const found = installedVersions.filter(e => e.includes(channelName)); + if (found.length === 1) + return path.join(folder, found[0], suffix); + if (found.length > 1) { + if (shouldThrow) + throw new Error(`Multiple Firefox installations found for channel '${name}': ${found.join(', ')}`); + else + return undefined; + } + if (shouldThrow) + throw new Error(`Cannot find Firefox installation for channel '${name}' under ${folder}`); + return undefined; + }; + return { + type: 'channel', + name, + browserName: 'bidi', + directory: undefined, + executablePath: (sdkLanguage: string) => executablePath(sdkLanguage, false), + executablePathOrDie: (sdkLanguage: string) => executablePath(sdkLanguage, true)!, + installType: 'none', + _validateHostRequirements: () => Promise.resolve(), + _isHermeticInstallation: true, + _install: install, + }; + } + private _createBidiChannel(name: BidiChannel, lookAt: Record<'linux' | 'darwin' | 'win32', string>, install?: () => Promise): ExecutableImpl { const executablePath = (sdkLanguage: string, shouldThrow: boolean) => { const suffix = lookAt[process.platform as 'linux' | 'darwin' | 'win32']; diff --git a/tests/bidi/README.md b/tests/bidi/README.md new file mode 100644 index 0000000000000..caac9288a4ae7 --- /dev/null +++ b/tests/bidi/README.md @@ -0,0 +1,23 @@ +## Running Bidi tests + +To run Playwright tests with Bidi: + +```sh +git clone https://github.com/microsoft/playwright.git +cd playwright +npm run build # call `npm run watch` for watch mode +npx playwright install chromium +npm run biditest -- --project='bidi-firefox-beta-*' +``` + +To install beta channel of Firefox, run the following command in the project root: +```sh +npx -y @puppeteer/browsers install firefox@beta +``` + +You can also pass custom binary path via `BIDIPATH`: +```sh +BIDIPATH='/Users/myself/Downloads/chrome-mac-arm64/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing' +``` + + diff --git a/tests/bidi/playwright.config.ts b/tests/bidi/playwright.config.ts index bc7b29e56bc8a..b04af32253f61 100644 --- a/tests/bidi/playwright.config.ts +++ b/tests/bidi/playwright.config.ts @@ -63,8 +63,8 @@ if (executablePath && !process.env.TEST_WORKER_INDEX) console.error(`Using executable at ${executablePath}`); const testIgnore: RegExp[] = []; const browserToChannels = { - '_bidiChromium': ['bidi-chrome-stable'], - '_bidiFirefox': ['bidi-firefox-stable'], + '_bidiChromium': ['bidi-chromium', 'bidi-chrome-canary', 'bidi-chrome-stable'], + '_bidiFirefox': ['bidi-firefox-nightly', 'bidi-firefox-beta', 'bidi-firefox-stable'], }; for (const [key, channels] of Object.entries(browserToChannels)) { const browserName: any = key;