DEV Community

Weather Clock Dash
Weather Clock Dash

Posted on

Firefox for Testing and Automation: geckodriver, Playwright, and CI Pipelines

Firefox is an excellent choice for automated testing and web scraping — it has official WebDriver support (geckodriver), a stable API, and unique features like network request interception that make it valuable in CI pipelines.

geckodriver: Firefox's WebDriver

Firefox uses geckodriver as its WebDriver implementation. Unlike Chrome's chromedriver which is bundled with Chrome, geckodriver is a separate download.

Setup:

# Download geckodriver from GitHub releases
# https://github.com/mozilla/geckodriver/releases
wget https://github.com/mozilla/geckodriver/releases/download/v0.34.0/geckodriver-v0.34.0-linux64.tar.gz
tar -xzf geckodriver*.tar.gz
sudo mv geckodriver /usr/local/bin/

# Verify
geckodriver --version
Enter fullscreen mode Exit fullscreen mode

Using with Selenium (Python):

from selenium import webdriver
from selenium.webdriver.firefox.options import Options

options = Options()
options.add_argument('--headless')  # Headless mode

driver = webdriver.Firefox(options=options)
driver.get('https://example.com')
print(driver.title)
driver.quit()
Enter fullscreen mode Exit fullscreen mode

Using with Selenium (Node.js):

const { Builder, By, until } = require('selenium-webdriver');
const firefox = require('selenium-webdriver/firefox');

const options = new firefox.Options().headless();
const driver = await new Builder()
  .forBrowser('firefox')
  .setFirefoxOptions(options)
  .build();

await driver.get('https://example.com');
console.log(await driver.getTitle());
await driver.quit();
Enter fullscreen mode Exit fullscreen mode

Firefox with Playwright

Playwright has first-class Firefox support using a patched Firefox build:

const { firefox } = require('@playwright/test');

// Launch Firefox
const browser = await firefox.launch({ headless: true });
const context = await browser.newContext();
const page = await context.newPage();

await page.goto('https://example.com');
console.log(await page.title());
await browser.close();
Enter fullscreen mode Exit fullscreen mode

Install Playwright Firefox:

npm install @playwright/test
npx playwright install firefox
Enter fullscreen mode Exit fullscreen mode

Firefox-specific options:

const browser = await firefox.launch({
  headless: true,
  firefoxUserPrefs: {
    'media.navigator.enabled': false,  // Disable media APIs
    'privacy.trackingprotection.enabled': false,  // Disable ETP for testing
    'network.http.speculative-parallel-limit': 0  // Disable speculative connections
  }
});
Enter fullscreen mode Exit fullscreen mode

Firefox Profile Management in Tests

Using a specific profile with geckodriver:

profile = webdriver.FirefoxProfile('/path/to/profile')
# Or create a temp profile with custom prefs:
profile.set_preference('network.proxy.type', 1)
profile.set_preference('network.proxy.http', 'proxy.example.com')
profile.set_preference('network.proxy.http_port', 8080)

driver = webdriver.Firefox(firefox_profile=profile)
Enter fullscreen mode Exit fullscreen mode

Pre-loaded cookies/session: If you need to test authenticated pages:

# Load an existing profile with saved session
profile = webdriver.FirefoxProfile('/path/to/profile-with-session')
driver = webdriver.Firefox(firefox_profile=profile)
driver.get('https://your-app.com/dashboard')
# Should be logged in from the profile's cookies
Enter fullscreen mode Exit fullscreen mode

Network Interception

With Playwright (more powerful than Selenium):

// Block external resources
await page.route('**/*.{png,jpg,gif,svg}', route => route.abort());

// Mock API responses
await page.route('**/api/users', async route => {
  await route.fulfill({
    status: 200,
    contentType: 'application/json',
    body: JSON.stringify([{ id: 1, name: 'Test User' }])
  });
});

// Intercept and log requests
page.on('request', request => {
  console.log(`${request.method()} ${request.url()}`);
});

// Intercept responses
page.on('response', response => {
  if (response.url().includes('/api/')) {
    console.log(`Response: ${response.status()} ${response.url()}`);
  }
});
Enter fullscreen mode Exit fullscreen mode

Capturing Screenshots and Videos

Playwright:

// Screenshot
await page.screenshot({ path: 'screenshot.png', fullPage: true });

// Video recording (configured at context level)
const context = await browser.newContext({
  recordVideo: { dir: 'videos/' }
});
const page = await context.newPage();
// ... test actions ...
await context.close(); // Saves the video
Enter fullscreen mode Exit fullscreen mode

Selenium:

driver.save_screenshot('screenshot.png')
# Full page screenshot requires scrolling manually or browser extension
Enter fullscreen mode Exit fullscreen mode

Geckodriver vs ChromeDriver Behavior Differences

User-Agent: Firefox's default UA differs from Chrome. If your site serves different content based on UA, tests may differ.

Network timing: Firefox's network stack has slightly different timing characteristics. Don't rely on exact timing in tests.

JavaScript timing: SpiderMonkey (Firefox's JS engine) can have different performance characteristics from V8 for CPU-intensive operations. Avoid time-sensitive tests.

Default behavior on unhandled alerts: Firefox and Chrome handle window.confirm() dialogs slightly differently in WebDriver mode. Explicitly handle or dismiss dialogs.

geolocation: Firefox prompts for permission; Chrome grants automatically in WebDriver mode. Handle geolocation permission in test setup:

// Playwright
const context = await browser.newContext({
  geolocation: { latitude: 40.7128, longitude: -74.0060 },
  permissions: ['geolocation']
});
Enter fullscreen mode Exit fullscreen mode

Testing Firefox Extensions

// Load a Firefox extension in Playwright
const context = await firefox.launchPersistentContext('/tmp/profile', {
  headless: false,
  firefoxUserPrefs: {
    'extensions.webextensions.temporary.install': true
  }
});
// Note: Loading unpacked extensions requires Playwright Firefox's specific API
Enter fullscreen mode Exit fullscreen mode

With web-ext + geckodriver:

# Run Firefox with extension and geckodriver for testing
web-ext run --pre-start-cmd='geckodriver &' --source-dir=./extension
Enter fullscreen mode Exit fullscreen mode

For CI testing of extensions, the typical approach is to use Playwright and load the extension's .xpi file.

Headless Firefox in Docker

FROM ubuntu:22.04

RUN apt-get update && apt-get install -y \
    firefox-esr \
    wget \
    && rm -rf /var/lib/apt/lists/*

# Install geckodriver
RUN wget https://github.com/mozilla/geckodriver/releases/download/v0.34.0/geckodriver-v0.34.0-linux64.tar.gz \
    && tar -xzf geckodriver*.tar.gz \
    && mv geckodriver /usr/local/bin/ \
    && rm geckodriver*.tar.gz

# Or use Playwright which manages its own Firefox
RUN npm install @playwright/test && npx playwright install firefox --with-deps

WORKDIR /tests
COPY . .
CMD ["npx", "playwright", "test", "--project=firefox"]
Enter fullscreen mode Exit fullscreen mode

Common Docker issues:

  • Missing fonts: Install fonts-freefont-ttf or fonts-noto
  • Missing WebGL: Add --disable-gpu equivalent: firefoxUserPrefs: { 'webgl.disabled': true }
  • X11 requirement for some versions: Use --headless mode explicitly

Web Scraping Considerations

Firefox for scraping: Firefox is a valid choice when:

  • The site detects Chrome-specific APIs and blocks scraping
  • You need extension-based automation (Firefox supports more flexible userScripts)
  • Your scraping requires matching Firefox's user-agent/fingerprint

Avoiding detection:

// Playwright Firefox with custom user-agent
const context = await browser.newContext({
  userAgent: 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0',
  viewport: { width: 1280, height: 720 }
});
Enter fullscreen mode Exit fullscreen mode

Ethical scraping note: Respect robots.txt, rate limit your requests, and review the site's terms of service before scraping.

Firefox in CI: GitHub Actions

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
      - run: npm install
      - run: npx playwright install --with-deps firefox
      - run: npx playwright test --project=firefox
Enter fullscreen mode Exit fullscreen mode

GitHub Actions provides ubuntu-latest which includes Firefox ESR. Playwright's --with-deps installs any system dependencies Firefox needs (fonts, libraries).

Top comments (0)