skip to content

Loaded Data Files

Reading canned data off disk with cy.fixture, aliasing it, and reaching files the fixtures folder does not hold. Asked because how a file is parsed decides what your test actually receives.

on this pageshow

explore

questions

5

In Cypress, how does cy.fixture('receipts') resolve a file with no extension?

level: juniorimportance: must knowfreq 76%

answer

  1. The folder Cypress looks in first
  2. A default folder underneath cypress/
  3. An exact filename beats any guess
  4. A fixed list of extensions, tried in order
  5. JSON first, zip last, no coffee

basics

~20 s

Cypress joins the path onto fixturesFolder, which defaults to cypress/fixtures. If that exact file exists it is read; otherwise Cypress tries a fixed extension list, .json first, and yields the first match, parsed according to that extension.

solid answer

~40 s

`cy.fixture('receipts')` resolves against `fixturesFolder`, which defaults to `cypress/fixtures`, so it is asking for `cypress/fixtures/receipts`. Cypress tries that literal path first; if no such file exists it matches the same stem against a fixed extension list and takes the first hit, in the order `.json`, `.js`, `.html`, `.txt`, `.csv`, `.png`, `.jpg`, `.jpeg`, `.gif`, `.tif`, `.tiff`, `.zip`. What you receive depends on which extension won: `.json` arrives as a parsed object, `.js` as the evaluated object literal, `.html`/`.txt`/`.csv` as strings, images and `.zip` as base64. Sub-paths work the same way, so `cy.fixture('receipts/approved.json')` reads `cypress/fixtures/receipts/approved.json`. As of Cypress 16, `.coffee` is no longer on that list. If nothing matches, the test fails with a fixture-not-found error naming the extensions Cypress tried.

code

javascript · 14 lines
javascript
// cypress/fixtures/receipts.json
// [{ "id": "R-1001", "merchant": "Blue Bottle", "amountCents": 1450 }]

it('shows the merchant on each receipt row', () => {
  cy.fixture('receipts').then((receipts) => {
    // resolved cypress/fixtures/receipts.json and parsed it
    expect(receipts[0].merchant).to.equal('Blue Bottle')
  })

  cy.fixture('receipts.json', 'utf8').then((raw) => {
    // an encoding was passed, so this is the unparsed text
    expect(raw).to.be.a('string')
  })
})

go deeper

for a junior

Be ready to say where fixture files live by default and what a JSON fixture hands your test. Knowing that cypress/fixtures is the default folder and that .json comes back parsed covers most screening questions here.

for a middle

Explain the resolution mechanics: literal path first, then a fixed extension list in a documented order, then parse by extension. Be able to say what a .csv or a .png fixture yields and how the encoding argument changes it.

for a senior

Show that you have been bitten by ambiguous fixture names and stale extension advice. Explain why you write extensions out on a shared suite and how you spot a fixture-not-found failure quickly when the command logs nothing.

for a principal

Own the convention: whether fixture names carry extensions, how the folder is laid out for a suite several teams edit, and how you keep advice about removed features such as CoffeeScript fixtures out of your onboarding docs.

## Where the path is resolved `cy.fixture()` never takes a path from your project root. The string you pass is joined onto the **`fixturesFolder`** configuration value, which defaults to `cypress/fixtures`, so in an expense-report suite `cy.fixture('receipts')` is a request for `cypress/fixtures/receipts`. Nested paths behave the same way: `cy.fixture('approvals/pending.json')` reads `cypress/fixtures/approvals/pending.json`. Two consequences fall straight out of that: - A file that does not live under the fixtures folder — a reimbursement CSV the app just downloaded, a generated report, `package.json` — is simply **out of reach** of this command. `cy.readFile()` is the command that takes a project-root-relative path. - If a project sets `fixturesFolder` to `false`, `cy.fixture()` is disabled entirely and throws rather than falling back to some other directory. ## The extension ladder Cypress tries the **literal path first**. If a file named exactly `cypress/fixtures/receipts` exists, extension or not, that is what you get. Only when the literal path is missing does Cypress guess, matching the same stem against a fixed list and taking the **first** hit: 1. `.json` 2. `.js` 3. `.html` 4. `.txt` 5. `.csv` 6. `.png`, `.jpg`, `.jpeg`, `.gif`, `.tif`, `.tiff` 7. `.zip` That order is the list's own — not alphabetical, not newest-file-first, and not influenced by which file you edited last. So if a team keeps both `receipts.json` and `receipts.csv` around, `cy.fixture('receipts')` silently resolves the JSON one forever. Nothing warns you that the CSV was skipped, which is why writing the extension out (`cy.fixture('receipts.csv')`) is worth the extra five characters whenever two files share a stem. ## What you receive depends on which extension won The whole point of this command is that it does not just hand you bytes — it parses. | Extension | What `.then()` receives | |---|---| | `.json` | a parsed JavaScript object or array | | `.js` | the evaluated object literal in the file | | `.html`, `.txt`, `.csv` | the file's text as a string | | `.png`, `.jpg`, `.jpeg`, `.gif`, `.tif`, `.tiff`, `.zip` | a base64-encoded string | | anything else | the text, read as `utf8` | So `cy.fixture('receipts')` and `cy.fixture('receipts.csv')` can hand the same test two completely different kinds of value: an array of expense objects you can index into, or one long string you would have to split yourself. A `.json` file that will not parse fails the test with a message naming the file — Cypress validates JSON and JavaScript fixtures rather than passing garbage downstream. ## The encoding argument short-circuits the parse `cy.fixture()` accepts an encoding as its second argument, and passing one changes the deal: - Pass **nothing** and you get the extension-driven behaviour in the table above. - Pass an encoding — even `'utf8'` — and Cypress returns the **raw file content** instead of parsing it, so `cy.fixture('receipts.json', 'utf8')` yields the JSON *text*, not an object. - Pass `null` and you get a `Cypress.Buffer` regardless of extension, which is what you want for a scanned receipt image you intend to hash or byte-compare. The encoding also forms part of the fixture cache key, so asking for the same file under two encodings is two separate reads rather than one. ## Cypress 16 dropped CoffeeScript Built-in CoffeeScript support was removed in **Cypress 16**: the default `@cypress/webpack-batteries-included-preprocessor` no longer bundles `coffee-loader`, and `.coffee` is no longer resolved for specs, support files, or `cy.fixture()`. Older blog posts and answers that list `.coffee` in the fixture extension order are describing a version that no longer exists. If a legacy project still has `.coffee` fixtures, the migration path is to convert them to JavaScript or JSON, or to wire the loader up in your own webpack configuration. ## When nothing matches If neither the literal path nor any extension in the list exists, the command fails with a fixture-not-found error that prints the relative path it tried and the extension list it searched. Two things make that failure easier to read: - `cy.fixture()` itself does **not** appear in the Command Log, so you are looking for the error, not for a greyed-out command entry. - The path in the error is relative to the project, which makes an accidental `cy.fixture('cypress/fixtures/receipts.json')` — a doubled folder prefix — obvious as soon as you read it.

  • Both receipts.json and receipts.csv exist. What does cy.fixture('receipts') read?
    The extension list decides, not the filesystem. `.json` is tried before `.csv`, so `cypress/fixtures/receipts.json` wins and you get a parsed object. Nothing warns you that the CSV was ignored, so pass the extension explicitly whenever two fixture files share a stem.
  • How do you read a receipt image as bytes rather than as a base64 string?
    Pass `null` as the encoding: `cy.fixture('scans/receipt.png', null)` yields a `Cypress.Buffer` regardless of the file extension. Without it, Cypress base64-encodes binary fixtures, which is convenient for building a data URI but useless if you want to check a byte length or a hash.

saying these in an interview costs you the question

  • Thinks cy.fixture() takes a path from the project root
  • Assumes every fixture arrives as a parsed object
  • Believes .coffee fixtures still resolve in Cypress 16
  • Expects alphabetical or newest-first extension matching
  • Says cy.fixture() can read any file in the repository
open as a page

In a Cypress test, how do you read fixture data aliased with .as('receipts')?

level: middleimportance: should knowfreq 58%

basics

~20 s

Two ways: this.receipts inside a test written with function(), because Cypress stores non-DOM aliases on Mocha's shared test context, or cy.get('@receipts') followed by .then(). Either only works after the queued .as() command has actually run.

open as a page

In Cypress, which files can cy.readFile() reach that cy.fixture() cannot?

level: middleimportance: should knowfreq 46%

basics

~20 s

Anything under the project root. cy.readFile() resolves its path from the folder holding the Cypress config, so it reads a downloaded reimbursement CSV or a generated report, while cy.fixture() is confined to fixturesFolder, by default cypress/fixtures.

open as a page

In a Cypress run, how many times does cy.fixture() actually read a file from disk?

level: seniorimportance: should knowfreq 36%

basics

~20 s

Once per path and encoding. Cypress caches the parsed contents in the browser-side driver and serves every later call from that cache, handing back a fresh clone each time so one test cannot corrupt another's copy.

open as a page

In Cypress, why is cy.fixture() a poor way to load a 40 MB receipt archive?

level: seniorimportance: nice to knowfreq 26%

basics

~20 s

Because it reads the whole file into memory in the Cypress Node process, ships it to the browser as a single internal WebSocket message, and keeps it cached. Large archives can exhaust memory or exceed socket buffer limits.

open as a page