skip to content

How far should a Cypress suite rely on `blackout` to keep customer data out of saved media?

level: principalimportance: should knowfreq 30%

answer

  1. It only paints over an image
  2. One capture type ignores it entirely
  3. That type is the one CI produces
  4. Recordings have no equivalent option
  5. Selectors drift, the data stays

basics

~20 s

Only as a tidiness measure on captures you ask for by name. Blackout is dropped for runner captures, and every automatic failure screenshot is a runner capture, so it never covers the image CI actually produces, and it never touches a video.

solid answer

~50 s

`blackout` takes an array of selectors and paints the matching elements out of the image, set per call or through `Cypress.Screenshot.defaults()`. It has three limits that decide how far you can lean on it. It applies only to app-only captures — `viewport` and `fullPage` — and is dropped for `runner` captures, which is exactly what the automatic failure screenshot is coerced to. It does nothing to a recorded video. And it is selector-based, so a redesign, a toast, a tooltip or an error page puts the data back on screen. My line: use it to hide the incidental on manual captures, and never treat it as the control that lets a suite point at real customer data. The durable answers are synthetic requesters, turning `screenshotOnRunFailure` off for the specs that render real records, and access control on the artefacts themselves.

code

javascript · 16 lines
javascript
// cypress/support/e2e.js
Cypress.Screenshot.defaults({
  // honoured for `viewport` and `fullPage` captures only —
  // the automatic failure screenshot is coerced to `runner`,
  // where this list is dropped
  blackout: ['[data-cy=requester-email]', '[data-cy=requester-name]'],
})

// cypress/e2e/tickets/queue.cy.js
describe('ticket queue', { screenshotOnRunFailure: false }, () => {
  it('lists open tickets for the on-call agent', () => {
    cy.visit('/tickets?status=open')
    cy.screenshot('queue-open', { capture: 'viewport' })
    cy.get('[data-cy=ticket-row]').should('have.length.greaterThan', 0)
  })
})

go deeper

for a junior

Know what blackout does to an image and how it is configured, and that it changes the picture rather than the page.

for a middle

Explain which capture types honour blackout and which drop it, and be able to name the automatic failure capture as one that drops it.

for a senior

Show the diagnosis path: why real data still reached an artefact, and which of the available switches you would actually reach for.

for a principal

Own the line across teams: what test data specs may render, which pipelines capture media, and who can read the artefacts afterwards.

## What `blackout` is `blackout` is an option on `cy.screenshot()` and on `Cypress.Screenshot.defaults()`. It takes an array of CSS selectors, and the elements they match are painted over in the saved image: ```javascript // cypress/support/e2e.js Cypress.Screenshot.defaults({ blackout: ['[data-cy=requester-email]', '[data-cy=requester-name]'], }) ``` On a support-ticket queue that renders real-shaped requester details, that is an appealing one-liner. The judgement question is whether it is a control you can stand behind, and the honest answer is that it is not — for three separate reasons. ## Limit one: it is dropped exactly where you need it Blackout is honoured for the app-only captures, `viewport` and `fullPage`. It is **dropped for `runner` captures**, and the screenshot Cypress takes automatically when a test fails is always coerced to a `runner` capture. So the arithmetic is unkind: the captures blackout covers are the ones you wrote deliberately and could simply not have taken, and the capture it does not cover is the one that appears without you asking, on the day a spec fails, on a CI machine, in an artefact anyone with pipeline access can download. ## Limit two: the video is untouched There is no blackout for a recording. When `video` is on, the spec is filmed as it ran, requester names included, for its whole duration. If the reason you reached for blackout was a screenshot, the video is the same exposure with more frames. ## Limit three: selectors drift, the data does not Blackout matches what you listed at the moment the capture is taken. It misses: - A column, tooltip, toast or expanded row that renders the same value somewhere you did not list. - A redesign that renames `[data-cy=requester-email]`, silently reducing the list to a no-op. - An error page or a partially rendered queue, where your selectors match nothing and the raw payload is on screen. - Anything that is not in the DOM you targeted at all — a page title, a URL with an account id in it. A control that fails open, silently, and is never asserted on is not a control. ## Where I draw the line 1. **Do not let blackout be the reason real customer data is in the run.** If the suite would be unacceptable without blackout, the fix is upstream: seeded, synthetic requesters whose names nobody minds seeing in an artefact. 2. **Use it for the incidental, on captures you name.** A signature block or an avatar in a `cy.screenshot('queue-open')` is a fine use. That is tidiness, and tidiness is worth something. 3. **When a spec genuinely must render real-shaped records, turn the capture off rather than dress it.** `screenshotOnRunFailure` can be set to `false` for a single suite or test through test configuration, and `video` can stay off for that pipeline. Say the cost out loud: that spec now fails in CI with no picture, and someone has to reproduce it locally. 4. **Put the real control on the artefact.** Who can download the job's artefacts, and how long they are kept, is a pipeline decision — and it is the one that actually binds, because it holds whether or not a selector matched. ## What this is not a decision about This is a data-protection line, not a judgement about how much evidence a suite is worth capturing. The two get tangled in interviews: someone answers "screenshot everything, blackout the sensitive bits" and has quietly decided both questions at once, on the strength of an option that does not reach the failure capture. ## How to argue it in the room - Name the coercion first — failure captures are `runner` captures, blackout is dropped there. It is the fact the position rests on. - Name the video gap second, because it is the part most candidates never mention. - Then give the ladder: synthetic data, capture disabled where it must be, artefact access as the backstop, blackout as cosmetics. - Be explicit about the cost you are accepting. A team that turns off failure screenshots for its most sensitive spec has traded diagnosability for exposure, on purpose, and should be able to say which specs those are.

  • Which captures does `blackout` actually apply to?
    The app-only ones: `viewport` and `fullPage`, and element captures, which are taken as viewport captures. It is dropped for `runner` captures — and since Cypress coerces the automatic failure screenshot to `runner`, blackout selectors never reach the image a failing CI run produces.
  • If you turn `screenshotOnRunFailure` off for a sensitive spec, what have you given up?
    The only automatic evidence that spec produces in CI. A failure now arrives as a reporter error with no picture, so triage means reproducing it locally or adding a named capture that you know renders nothing sensitive. It is a real trade, and worth stating as one.

saying these in an interview costs you the question

  • Calls blackout a data-protection control
  • Forgets that failure captures ignore blackout entirely
  • Never mentions that the video is not blacked out
  • Assumes a selector list stays correct after a redesign
  • Offers no fallback when capture must be disabled