O Safari representa 27% do tráfego web mobile. Todo navegador iOS, incluindo o Chrome no iPhone, roda em WebKit por baixo, o que significa que pular o WebKit é pular seus usuários de iPhone. Chrome e Edge compartilham a mesma engine Chromium, então juntos cobrem aproximadamente 78% do tráfego desktop com um único projeto de navegador.

Por que os navegadores ainda diferem

Navegadores modernos (Chrome, Firefox, Safari, Edge) todos suportam os mesmos padrões de HTML, CSS e JavaScript. Mas as diferenças persistem:

Renderização de CSS: Gaps de flexbox, comportamentos de grid, renderização de fonte, shadow DOM: os navegadores implementam as specs de forma levemente diferente. APIs JavaScript: Algumas APIs mais recentes não são suportadas em versões mais antigas do Safari. Array.at(), structuredClone(), ResizeObserver: todos têm suporte variável. Elementos de formulário: Date pickers, inputs de arquivo, elementos select: os navegadores têm estilos e comportamentos diferentes. Renderização de PDF: O Safari lida com PDFs diferente do Chrome. Específico do WebKit: O iOS usa WebKit para todos os navegadores (sim, o Chrome no iPhone é WebKit por baixo). Safari no Mac = Safari no iPhone.

Participação de mercado dos navegadores (2025)

| Navegador | Desktop | Mobile |

|-----------|---------|--------|

| Chrome | ~65% | ~66% |

| Safari | ~12% | ~27% |

| Firefox | ~3% | ~1% |

| Edge | ~13% | ~3% |

Ponto-chave: Safari é crítico para mobile (iPhone é WebKit). Edge é baseado em Chrome (Chromium). Firefox tem baixa participação de mercado mas é importante para enterprise e regiões específicas.

A estratégia pragmática

Você não pode testar tudo em todo navegador. Uma hierarquia prática:

Camada 1: Sempre testar (todo sprint)

  • Chrome — maior participação de mercado, navegador principal de desenvolvimento
  • Safari — crítico para usuários iOS/macOS

Camada 2: Testar antes de releases maiores

  • Firefox — menor participação de mercado mas renderização distinta
  • Edge — baseado em Chromium, risco adicional baixo

Camada 3: Testar para features específicas

  • Safari iOS — ao testar fluxos específicos de mobile
  • Chrome Android — comportamentos específicos de mobile
  • Versões específicas de navegador — quando clientes enterprise as exigem

Configuração cross-browser no Playwright

O Playwright suporta Chrome, Firefox e WebKit (a engine do Safari) nativamente:

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  projects: [
    // Navegadores desktop
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
    {
      name: 'firefox',
      use: { ...devices['Desktop Firefox'] },
    },
    {
      name: 'webkit',
      use: { ...devices['Desktop Safari'] },
    },
    
    // Navegadores mobile
    {
      name: 'mobile-chrome',
      use: { ...devices['Pixel 7'] },
    },
    {
      name: 'mobile-safari',
      use: { ...devices['iPhone 14'] },
    },
  ],
});

Rodar um navegador específico:

npx playwright test --project=webkit

Rodar todos os navegadores:

npx playwright test

O que testar cross-browser (e o que não testar)

Teste cross-browser:
  • Fluxos principais do usuário (login, checkout, workflows principais)
  • Formulários, especialmente date pickers, uploads de arquivo, selects
  • Layout CSS, especialmente designs com flex/grid intenso
  • Features com muito JavaScript (interações complexas)
  • Fluxos específicos de mobile (touch, viewport, orientação)
Não precisam de testes cross-browser:
  • Testes unitários: independentes de navegador
  • Testes de API: sem navegador envolvido
  • Testes de lógica de backend
  • Ferramentas admin internas que só seu time usa

Lidando com falhas específicas de navegador

Quando um teste falha em apenas um navegador:

test('file upload', async ({ page, browserName }) => {
  // Pular no WebKit — o comportamento de file input difere significativamente
  test.skip(browserName === 'webkit', 'WebKit handles file inputs differently');
  
  await page.goto('/upload');
  await page.setInputFiles('[data-testid="file-input"]', 'test-file.pdf');
  await expect(page.getByTestId('upload-success')).toBeVisible();
});

Quando você precisa de comportamento específico por navegador:

test('date picker works', async ({ page, browserName }) => {
  await page.goto('/book-appointment');
  
  if (browserName === 'webkit') {
    // O date picker do Safari exige interação diferente
    await page.fill('[data-testid="date-input"]', '2026-06-15');
  } else {
    await page.click('[data-testid="date-input"]');
    await page.click('[data-date="2026-06-15"]');
  }
  
  await expect(page.getByTestId('selected-date')).toContainText('June 15');
});

BrowserStack e Sauce Labs

Os navegadores integrados do Playwright usam versões open-source. Para testar no Chrome real (não Chromium), Safari real e versões específicas de navegador, use serviços de teste em nuvem.

BrowserStack

// playwright.config.ts para BrowserStack
const capabilities = {
  'browserstack.user': process.env.BROWSERSTACK_USERNAME,
  'browserstack.key': process.env.BROWSERSTACK_ACCESS_KEY,
};

export default defineConfig({
  projects: [
    {
      name: 'chrome@latest-mac',
      use: {
        connectOptions: {
          wsEndpoint: `wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(JSON.stringify({
            ...capabilities,
            browserName: 'chrome',
            browserVersion: 'latest',
            'bstack:options': {
              os: 'OS X',
              osVersion: 'Sonoma',
            }
          }))}`,
        },
      },
    },
  ],
});

Quando serviços em nuvem valem a pena

  • Você precisa do Safari real (não WebKit) em macOS real
  • Versão específica do Chrome (clientes enterprise travados no Chrome 110)
  • Testes em dispositivos iOS reais (não simulador)
  • Suporte a IE11 (raro, mas ainda existe em finanças/governo)

Testes responsivos

Teste em múltiplos tamanhos de viewport, não apenas mobile vs desktop:

// playwright.config.ts
projects: [
  {
    name: 'desktop',
    use: { viewport: { width: 1920, height: 1080 } },
  },
  {
    name: 'laptop',
    use: { viewport: { width: 1280, height: 720 } },
  },
  {
    name: 'tablet',
    use: { viewport: { width: 768, height: 1024 } },
  },
  {
    name: 'mobile',
    use: { viewport: { width: 375, height: 667 } },  // iPhone SE
  },
],

Dentro de um teste:

test('navigation works on mobile', async ({ page }) => {
  await page.setViewportSize({ width: 375, height: 667 });
  await page.goto('/');
  
  // Mobile: menu hamburger em vez de barra de nav
  await expect(page.getByTestId('hamburger-menu')).toBeVisible();
  await expect(page.getByTestId('desktop-nav')).not.toBeVisible();
  
  await page.getByTestId('hamburger-menu').click();
  await expect(page.getByTestId('mobile-nav')).toBeVisible();
});

Gerenciando falhas cross-browser no CI

Rode navegadores em paralelo para manter o CI rápido:

# Estratégia de matrix no GitHub Actions
strategy:
  matrix:
    browser: [chromium, firefox, webkit]

steps:
  - run: npx playwright test --project=${{ matrix.browser }}

Ou faça sharding de testes cross-browser:

strategy:
  matrix:
    include:
      - browser: chromium
        shard: 1/2
      - browser: chromium  
        shard: 2/2
      - browser: firefox
        shard: 1/1  # Menos testes Firefox
      - browser: webkit
        shard: 1/1

Testes visuais cross-browser

Diferenças de renderização CSS são frequentemente sutis. A comparação manual é trabalhosa. Use Percy ou a comparação de screenshots do Playwright:

test('homepage renders correctly', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveScreenshot('homepage.png', {
    maxDiffPixelRatio: 0.02,  // 2% de diferença de pixel permitida
  });
});

Screenshots são armazenados por projeto: cada navegador tem seu próprio baseline.

Resumo

Estratégia prática de cross-browser:

1. Rode a suite completa no Chrome em todo commit

2. Rode Chrome + Safari antes de todo release

3. Rode todos os navegadores (incluindo Firefox, Edge) antes de releases maiores

4. Teste viewports mobile para features responsivas

O Playwright torna o cross-browser fácil:
  • Defina projetos para cada navegador
  • Fixture browserName para código específico de navegador
  • test.skip() para incompatibilidades conhecidas
  • WebKit integrado = Safari sem precisar de macOS

O objetivo não é testar tudo em todo navegador: é pegar os bugs específicos de navegador que realmente afetam seus usuários, usando o tempo que você tem.

→ Veja também: Testes Cross-Browser com Playwright: Chrome, Firefox, Safari | Emulação Móvel no Playwright: Testes Responsivos e Táteis | Execução Paralela no Playwright: Workers, Shards e Sharding para Velocidade