Cypress vs Playwright Advent Calendar Day 12
Use data from a JSON fixture file in your test
Yesterday we started using an array of “todo” items to set the initial test state with a single API network call. Let’s move the initial data into a JSON file. I will place the list of “todo” items into the fixtures/3-todos.json file.
[
{
“title”: “Write code”,
“completed”: false,
“id”: “9719548620”
},
{
“title”: “Write tests”,
“completed”: false,
“id”: “7560280342”
},
{
“title”: “Make tests pass”,
“completed”: false,
“id”: “8607162111”
}
]Great, let’s import and use this JSON data from our spec files. In all cases, we want to confirm that the list of items has a few todos before using it.
Playwright imports JSON fixture data
Playwright runs its test in Node, so importing a JSON fixture is obvious.
import { test, expect } from ‘@playwright/test’
import todos from ‘../fixtures/3-todos.json’
expect(todos.length, ‘have a few todos’).toBeGreaterThan(2)
test.describe(’TodoMVC’, () => {
test.beforeEach(async ({ request }) => {
await request.post(’/reset’, { data: { todos } })
})
test(’completes a todo’, async ({ page }) => {
await page.goto(’/’)
await expect(page.locator(’.todo-list li’)).toHaveCount(todos.length)
})
})The test passes.
Note that our check of number of imported items is NOT shown in the UI
expect(todos.length, ‘have a few todos’).toBeGreaterThan(2)The assertion still works; you can verify it by changing the min number to something really large to make it fail on purpose
// make it fail on purpose
expect(todos.length, ‘have a few todos’).toBeGreaterThan(20)The terminal output view also shows this error
Nice.
Cypress imports JSON fixture data
Cypress includes a bundler that can import JSON files automatically into the browser spec.
import todos from ‘../../fixtures/3-todos.json’
// confirm we have a few todos imported
expect(todos, ‘have a few todos’).to.have.length.greaterThan(2)
describe(’TodoMVC’, () => {
beforeEach(() => {
cy.request(’POST’, ‘/reset’, { todos })
})
it(’completes a todo’, () => {
cy.visit(’/’)
cy.get(’.todo-list li’).should(’have.length’, todos.length)
})
})The test is green.
Notice that the initial assertion is outside any test and is not reflected in the Command Log, just like it is not shown in Playwright test runner.
// confirm we have a few todos imported
expect(todos, ‘have a few todos’).to.have.length.greaterThan(2)What’s up with test runners “losing” an assertion outside a test / test hook?! The assertion still works - you can confirm it by changing the minimum number of items to 20 for example to see it fail
// confirm we have a few todos imported (fails on purpose)
expect(todos, ‘have a few todos’).to.have.length.greaterThan(20)Beautiful.
While You Are Here
Check out a couple of my latest blog posts:
“Branded Types” blog post shows how to quickly create custom TS types that remove any ambiguity between things like “cents vs dollars” and “milliseconds vs seconds” in your test specs.
“Test Auto-healing Is A Red Flag” expresses my opposition to Cypress (and other companies) pushing “auto-healing” of tests using AI guesses. Auto-healing hides real problems in your application and shows only one thing: your development process allows changes to the code to be merged without running / updating tests.
“How To Type Function Mocha Context With Cypress Aliases” covers a pretty specific topic that is not covered by Mocha / Cypress documentation: how to give types to the custom properties aliased in your tests. Here is one solution example screenshot, read the blog post for the full explanation
This advent calendar is based on my online course “Cypress vs Playwright“ and open-source workshop bahmutov/cypress-workshop-cy-vs-pw. You can find links to the previous advent calendar days in my blog post “Cypress vs Playwright Advent Calendar 2025“.







