Let me get back to the testing of negative states one more time. Recently, I have read a pretty good blog post How to test that cache works with Cypress by Walmyr. A piece of Cypress test syntax caught my eye: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 cy.search(randomWord).then(() => { expect(count, `network…
Gleb Bahmutov
https://glebbahmutov.com/blog/ · 30 posts · history since 2025 · active
Yesterday
22 May
Imagine a simple web application scenario: you click on a button. App tries to load some data. The data might load, or the backend might return an error. You write a Cypress test: 1 2 3 cy.visit('cypress/fetch-fails-sometimes.html') cy.contains('button', 'Fetch data').click() cy.contains('#data', 'Fetched data: "List of items"') The test is green, but there are a couple of downsides. test is slow…
28 Apr
Cypress-the-company is putting a lot of effort behind its cy.prompt command (which I recreated in cypress-think), so let's see if it is any good. I took a simple login form and tried to create a test using three different approaches: coding in VSCode using "update the test / Cypress reruns it / update the test" using cy.prompt command from text…
23 Apr
Finally, it has happened. Cypress v15.14 supports TypeScript v6. This is a big deal - TypeScript v6 is the last step before TypeScript v7 which is implemented in Go and is much faster. By the way, you can try TypeScript v7 beta today. So what do you need to switch your projects to use TS v6 with Cypress? It is…
7 Apr
I have a little web app called Gametime I use to keep track of players during youth soccer matches. Recently I decided to add a11y testing to ensure the text is readable, inputs have labels, etc. Since I already had Cypress end-to-end tests covering all features of the app, I just needed 60 seconds to ensure the web app is…
21 Mar
Every individual item sold on Mercari.com has an id that looks like m<number>. The item's id is visible in the URL, for example www.mercari.com/us/item/m73702188949/. If you buy several items from the same seller, you get a discount because you buy it as a bundle. Every bundle has its own unique id that looks like b<number>. Both ids are strings, yet…
12 Mar
Recently Cypress announced a change in how it will handle environment variables. Variables were always public and accessible to the application under test in the browser (via calling Cypress.env() method), but now you can have truly private values. I published a blog post Migrating From Cypress.env To cy.env and Cypress.expose Methods describing the change. Looking at the changes, I noticed…
7 Mar
Cypress v15.10.0 has announced a big switch coming in v16 - the new way of dealing with environment values and secrets. Let's see why this change is necessary, what is means for your testing code, and what the best practices for handling secrets in your tests should be. First, let me say: Cypress end-to-end browser tests run in the browser.…
23 Feb
At the end of 2025, NPM registry revoked all personal NPM tokens that I used to publish new NPM package releases. This change improves the security of the entire NPM publishing workflow, but has disrupted my CI process. For example, the new feature of cypress-timestamps has not been released, failing with the error "SemanticReleaseError: Invalid npm token.". Hmm, what do…
11 Feb
Imagine you are testing a TodoMVC application, and you need to complete all items. You simply click every checkbox and confirm the application preserves the "0 todos left" state. Normally everything goes well: But sometimes a weird thing happens: one or more checkboxes remain unchecked! 📺 Watch the examples in this blog post explained in my video. You start looking…
8 Jan
If you are testing a website, the DEV dependencies do not change very often. You might bump Cypress version once in a while, add or upgrade a Cypress plugin, but in general the Node dependencies are changed less frequently than the spec files. Thus running npm ci on every test job is bound to be repetitive work that slows down…
7 Jan
This year I am reclaiming my attention span away from my iPhone. Lately, I have noticed that while reading or working, I reach for my phone to check email / BlueSky every couple of minutes. I tried to force myself to focus on work / book by using a timer; do not touch the phone until the timer is up.…
30 Dec 2025
Here is something I have noticed about my projects and using Copilot lately. When I add a new NPM dependency, I also update the Copilot instructions file to include examples of how I want to use that dependency in my tests. For example, let's say I need to test if item prices on the inventory page are sorted. We can…
26 Dec 2025
Loading skeletons are displayed while the real data is loading. For example, the login passwords are displayed after 1 second in the GIF below, and the loading skeleton is displayed first. The skeleton itself is simple, just a DIV with some gradient CSS. src/pages/Login.jsx 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16…
11 Dec 2025
In Cypress you can save values under aliases which is pretty handy. You can get the aliased value using the cy.get, or by using a cy.then(function () { ... }) callback, or (my favorite solution) using the alias in the next hook or test callback via this.[alias] property 1 2 3 4 5 6 7 8 9 10 11 12…
10 Dec 2025
Well, I am happy to report Cypress-the-company is all in on test auto-healing in its new cy.prompt command (which I recreated locally as cypress-think plugin). Let's look at the screenshots Cypress put in the blog post: The test shows Cypress auto-healing in practice. The test had a prompt like "Turn on dark mode", which used to resolve to some button…
5 Dec 2025
Let's say you need to specify a timeout or wait in your end-to-end Cypress tests. You would use milliseconds 1 2 3 4 // try finding the "selector" elements for up to 1 second cy.get('selector', { timeout: 1_000 }) // then wait for 5 seconds .wait(5_000) For clarity, you could write a helper to convert seconds into milliseconds 1 2…
1 Dec 2025
This year I am producing "Cypress vs Playwright Advent Calendar" on my Cypress Tips newsletter. Day 1: global vs local variables Day 2: The difference in test command syntax Day 3: DOM Snapshots vs live application Day 4: Where do the end-to-end tests run? Day 5: Locators and selectors Day 6: Composite locators vs query chains Day 7: Comparing the…
30 Nov 2025
Imagine we are testing a web page that receives two numbers from the server and then shows their sum In the Command Log you can see the two GET /random-digit calls the web page makes to the server. The server responds with {n: ...} JSON object. The page should add these two numbers and show the correct sum How would…
9 Oct 2025
I have described using Use Copilot Instructions And Page Objects to quickly develop end-to-end Cypress tests. This blog post gives another concrete example. You can find the source code in the repo bahmutov/copilot-instructions-example. First, I wrote a page object file to implement common TodoMVC application test commands: visit the app and wait for it to load reset the backend data…
3 Oct 2025
Imagine you are testing a web page showing the purchase receipt. When the user clicks on the "View Summary" button, a dialog pops up showing just the total amount paid cypress/e2e/receipt.cy.js 1 2 3 4 5 6 describe('Receipt', () => { it('shows the price on the receipt', () => { cy.visit('app/index.html') cy.contains('button', 'View Summary').click() }) }) How would you confirm…
30 Sept 2025
Recently I watched a pretty good video Cypress vs Playwright side-by-side coding comparison. by Artem Bondar. While not as good as my Cypress vs Playwright course, the video is pretty solid. There is one point Artem makes in the beginning that he did not stress enough, but which determines how each tool gives you the access to the browser and…
28 Sept 2025
Testers and developers often use page objects to interact with their web applications via DOM elements. Let's create a page object for our TodoMVC app: cypress/e2e/todo.ts 1 2 3 4 5 6 7 8 9 export const TodoMVC = { addTodo(title: string) { cy.get('.new-todo').type(`${title}{enter}`) }, getTodos() { return cy.get('.todo-list li') }, } All tests that add a todo item and…
23 Sept 2025
As I explained in my previous blog post on feature flags and testing, you need the flags to be the same to ensure consistent application behavior during end-to-end tests. If you want to test the specific feature, control the flag from the test. But sometimes the tests unexpectedly fail when one of the developers or QA engineers is testing something…
22 Sept 2025
I have shown how to use Copilot instructions file to generate better end-to-end Cypress tests. In this blog post I will show a specific trick I use to make my test writing a lot more precise and much faster. When we are writing end-to-end tests, we constantly need to look up the best test selectors to use to find elements…
16 Sept 2025
If your web application stores data locally in the localStorage object, you can easily set / verify the data from your Cypress end-to-end tests. For example: cypress/e2e/players.cy.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33…
9 Sept 2025
In the blog post Test Tag Suggestions Using AI I described a system to pick a testing tag based on a pull request's title and body text. In this blog post, I will make it useful. Whenever a user opens a GitHub issue and labels it a "bug", an automated workflow will pick an appropriate testing tag (or several) and…
3 Sept 2025
Ask Copilot agent to write the full end-to-end test and it is likely to write nonsense. For example, let's test the "zero teams / zero players" message on my soccer web app. I can start a new test in the existing "Teams" spec file cypress/e2e/teams.cy.js 1 2 3 describe('Teams', () => { it.only('shows zero teams and zero players message', ()…
20 Aug 2025
Here are a couple of newsletters I subscribe to keep up-to-date on Node.js, JavaScript, front-end development, and testing. Smashing Magazine newsletter has high-quality front-end, CSS, and design articles WebTools weekly is a weekly round-up of apps, scripts, plugins, and other resources to help front-end and full-stack web developers solve problems and build great websites. JavaScript Weekly is a newsletter of…
16 Jul 2025
How does a human quality assurance engineer (QA) test a web application? If I ask you to look at this TodoMVC web app, how do you know what features it has? From your life experience, you might guess that this app lets the user enter new Todo items and should show them in the list somewhere below the input element.…