> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devinenterprise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Detecte Regressões Visuais Antes de Cada PR

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="Detectar regressões visuais antes de cada PR" description="Uma habilidade de repositório que instrui o Devin a tirar capturas de tela de cada página afetada e sinalizar quebras de layout antes de abrir um PR." prompt="Crie uma habilidade de repositório em .agents/skills/visual-regression/visual-regression.md que explique ao Devin como iniciar nosso app Next.js, navegar por todas as páginas afetadas pelo diff atual, tirar capturas de tela em larguras de desktop e mobile e sinalizar quaisquer problemas de layout — antes de abrir um PR." category="Desenvolvimento de recursos" features="Habilidades" />

<div className="uc-detail-wrapper">
  <Tip>Não quer configurar isso manualmente? Cole um link para esta página em uma sessão do Devin e peça que ele configure tudo para você.</Tip>

  <Steps>
    <Step title="O problema: erros de CSS passam despercebidos pelos testes unitários">
      Sua suíte de testes passa, o CI está verde e o PR é mesclado — mas a página de configurações agora tem texto sobreposto no mobile, e o botão de checkout desapareceu atrás de um rodapé. Testes unitários e linters não detectam quebras visuais, então isso vai para produção e um cliente reporta o problema.

      Uma skill de repositório resolve isso. Skills são arquivos Markdown que você faz commit em `.agents/skills/<your-skill>/` em qualquer um dos seus repositórios. Devin vê todas as skills em todos os repositórios conectados — você pode acioná-las manualmente ou o Devin pode escolher acioná-las automaticamente quando detectar uma situação relevante. Esta skill diz ao Devin exatamente como inicializar seu app, navegar pelas páginas afetadas pelo diff e tirar capturas de tela delas em múltiplas larguras de viewport — sempre, antes de cada PR.
    </Step>

    <Step title="Adicione a skill de regressão visual ao seu repositório">
      Faça um commit de um arquivo em `.agents/skills/visual-regression/visual-regression.md` que represente a lista de verificação de QA manual da sua equipe como etapas que o Devin possa seguir:

      ```markdown theme={null}
      # Visual Regression Check

      ## Description
      Before opening any PR, start the app locally and screenshot every
      page affected by the current diff at desktop and mobile widths.
      Flag any layout issues found.

      ## Prerequisites
      - Docker running (for the database)
      - Port 3000 available

      ## Setup
      1. Install dependencies: `npm install`
      2. Start services: `docker-compose up -d postgres redis`
      3. Run migrations: `npx prisma migrate dev`
      4. Seed test data: `npm run db:seed`
      5. Start the dev server: `npm run dev`
      6. Wait for "Ready on http://localhost:3000" in the terminal

      ## Visual Checks
      1. Read the current git diff to identify which pages are affected
      2. For each affected page:
         a. Open the page in the browser at http://localhost:3000/{route}
         b. Screenshot at 1280px width (desktop)
         c. Resize the browser to 375px width (mobile)
         d. Screenshot at mobile width
         e. Check for: overlapping text, elements hidden behind other
            elements, horizontal scroll, buttons or links that are
            unreachable, missing images or icons, console errors
      3. If any issue is found, list it with the page URL, viewport
         width, and a description of the problem

      ## Before Opening the PR
      1. Run `npm run lint` and fix any issues
      2. Run `npm test` and confirm all tests pass
      3. Include all screenshots in the PR description
      4. If issues were found, list them at the top of the PR body
      ```

      Este arquivo vem junto com o seu código. Depois de incluído em um commit, o Devin o vê como uma habilidade disponível — sempre que uma sessão interagir com arquivos de UI neste repositório, o Devin pode acionar os testes de regressão visual automaticamente, ou você pode executá-los manualmente a qualquer momento.
    </Step>

    <Step title="Torne as verificações específicas para suas páginas">
      Instruções genéricas como "verifique se a página parece correta" produzem resultados vagos. A parte mais valiosa dessa skill é dizer ao Devin como é o comportamento correto em cada área do seu app.

      Adicione seções específicas de rota à sua skill:

      ```markdown theme={null}
      ## Route-Specific Checks

      ### Dashboard (`/dashboard`)
      - The metric cards should display in a 3-column grid on desktop
      - Cards should stack to a single column on mobile
      - The chart should be fully visible without horizontal scroll

      ### Checkout (`/checkout`)
      - The "Place Order" button must be visible without scrolling
        on both desktop and mobile
      - The order summary sidebar should collapse into an accordion on mobile
      - The price breakdown should show subtotal, tax, and total on separate lines

      ### Settings (`/settings`)
      - All form labels should be left-aligned with their inputs
      - The "Save" button must be reachable at the bottom of the form
      - Tab navigation between sections should update the URL hash
      ```

      Devin lê o diff, identifica quais rotas foram afetadas e segue a seção correspondente — assim, as verificações são direcionadas em vez de genéricas.
    </Step>

    <Step title="Veja-o identificar uma regressão real">
      Suponha que um(a) engenheiro(a) altere o grid CSS no dashboard de `grid-template-columns: repeat(3, 1fr)` para `repeat(auto-fit, minmax(200px, 1fr))` para tornar o layout responsivo. Os testes unitários passam — nenhuma lógica mudou. Mas, no mobile, os cards agora extrapolam a largura da viewport.

      Quando o Devin termina a mudança de código, ele segue a skill automaticamente:

      1. **Inicializa o app** — instala dependências, inicia o Docker, executa migrações, faz o seed dos dados, inicia o servidor de desenvolvimento
      2. **Lê o diff** — vê que `src/components/Dashboard.tsx` mudou, mapeia isso para a rota `/dashboard`
      3. **Captura screenshots em 1280px** — o grid de 3 colunas é renderizado corretamente
      4. **Captura screenshots em 375px** — identifica overflow horizontal: os cards não cabem na viewport
      5. **Sinaliza o problema** — reporta "Rolagem horizontal detectada em /dashboard com largura de 375px — cards de métricas extrapolam a viewport"
      6. **Corrige o CSS** — adiciona `overflow-x: hidden` e ajusta o mínimo do `minmax` para `150px`
      7. **Captura novos screenshots** — confirma a correção em ambas as larguras
      8. **Abre o PR** — inclui screenshots de antes/depois e a correção na descrição

      Você pode assistir a isso acontecer em tempo real pela aba do navegador no seu [espaço de trabalho da sessão](/pt-BR/work-with-devin/devin-session-tools).
    </Step>

    <Step title="Integre ao seu stack">
      Adapte a skill para ferramentas adicionais e etapas de verificação específicas do seu projeto:

      <PromptBlock>
        ```txt Adicionar verificações de componentes do Storybook theme={null}
        Atualize a skill de regressão visual para também executar
        `npm run storybook`, abrir http://localhost:6006 e fazer uma captura de tela
        de cada story dos componentes modificados no diff atual. Sinalize
        quaisquer stories que apresentem erro de renderização ou tela em branco.
        ```
      </PromptBlock>

      <PromptBlock>
        ```txt Adicionar verificação do modo escuro theme={null}
        Atualize a skill de regressão visual para também alternar o app para o modo escuro
        (clicando no alternador de tema no canto superior direito) e refazer as capturas de tela de
        todas as páginas afetadas. Sinalize qualquer texto que fique ilegível no
        fundo escuro ou qualquer elemento que perca sua borda.
        ```
      </PromptBlock>
    </Step>
  </Steps>
</div>
