Artem Zakharchenko
banner
kettanaito.com
Artem Zakharchenko
@kettanaito.com
Software engineer. Helping you master automated testing at http://EpicWeb.dev. Author mswjs.io. Instructor egghead.io.

I tell stories @zakarcher.com.

My debut book "LOGGERHEADS" it out 👇
https://zakarcher.com/books/loggerheads
Do you know why some emitters return a boolean when you emit an event?

Because that allows you to know if that event had listeners, i.e. was expected and handled. And craft a proper experience in case it wasn't!
January 16, 2026 at 5:36 PM
What do you think about this analogy for the testing levels? Does this make things a bit more clear to you? 👀
January 8, 2026 at 9:44 PM
This paragraph makes me extremely sad.
January 8, 2026 at 1:56 PM
Wait, new episode? 👀
January 7, 2026 at 9:54 PM
💡 I used to be confused about using accessibility selectors in tests. Which exact elements will they match? Is "role" really enough?

No, it's not! Give your elements *accessible names*. Describe what they are on top of their roles. It's like specificity in CSS!
January 6, 2026 at 3:19 PM
Here's the shortest way I know how to explain why static types aren't a substitute for unit tests. Types declare contracts, and that is valuable, but they do not describe nor control runtime logic.
January 4, 2026 at 8:37 PM
Writing update: the second draft of my fantasy novel has surpassed 80,000 words. Nearing the half of the book. I have to finish this colossus this year.
January 2, 2026 at 4:53 PM
Remember when GitHub showed you how people discovered your projects? A jolly good time that was.
December 28, 2025 at 1:37 PM
The state of typography in fantasy, circa 2025.
December 27, 2025 at 10:24 PM
The kind soul that got themselves my book before Christmas, thank you! Enjoy the story, and merry holidays! ❤️
December 23, 2025 at 11:06 PM
📰 Today, I'm writing about an API so dark, so magical, you should never use it in your product code. Naturally, I've used it in my tests and let me show you how.

Let's talk about Symbol.iterator and how the spread syntax works in JavaScript.
December 18, 2025 at 2:48 PM
Here's what I ended up with instead.

`showModal` *renders* the dialog dynamically with the provided "props" and returns a Promise that resolves when the user closes the dialog.
December 17, 2025 at 4:26 PM
For a while, I thought this was the pinnacle dialog experience. Until I realized this isn't how I want to consume dialogs. Let me explain.
December 17, 2025 at 4:26 PM
I just got my CI from 6m44s down to 4m7s and it took ONE change in Playwright config.

How come nobody ever told me Playwright fails to properly calculate the number of cores your CI machine has? This tiny screenshot screams of MONTHS of time wasted on CI over the years.
December 17, 2025 at 4:05 PM
My novelette, Loggerheads, is 50% off for the holidays! That includes both digital and physical editions.

A perfect story to get oneself lost in with a hot cup of tea in your hand and a crackling fireplace by your side. Get yourself a copy below 👇
December 17, 2025 at 3:12 PM
When designing your APIs it's natural to want to name things for what they are. But when choosing method names, it's often much better to let the name describe what the method *does* instead of what it is.

Compare these two (see what I did here?):
December 12, 2025 at 4:56 PM
One of the interesting challenges on recent memory is this: how do you "refresh" images pointing to local (cached) resources after you *replaced* the buffer for those resources?

Previously, I had to design React hook hackery to update those images. Not anymore.
December 10, 2025 at 6:31 PM
Here's how a good error message could've looked like.

Every good error message has three parts:
- What went wrong.
- Likely why it went wrong.
- Instructions to recover.
December 9, 2025 at 4:47 PM
Publishing a new version of the package that's already published to npm.

Do you want to guess what *actually* caused this error?
Post your answer. Will post the correct answer below.
December 9, 2025 at 4:47 PM
I'm so glad to see iPhone Air win the best design award. Originality and ingenuity have to be appreciated. Good job.
December 9, 2025 at 4:31 PM
I've been doing open source for a decade now. I remember dreaming about becoming smart enough to contribute to the projects I myself used. I've contributed here and there but mostly built my own stuff.

Last week was I got invited to Zustand as a contributor.

❤️
December 9, 2025 at 3:47 PM
This is the simplest way I can describe the main point and appeal of Remix 3: You work with events.

Aside from native DOM events for managing things like form inputs or "outerPress", anything can become an EventTarget and anything can subscribe to events on any targets.
December 8, 2025 at 10:30 PM
Playing Kingdom Come Deliverance 2. Entering a random kitchen in a random village.

Someone from another room: *to himself* Kurva...

10/10 game, totally recommend.
December 3, 2025 at 5:09 PM
ESM is absolutely goated for testing. Check out how I'm reusing my Zustand store to put my app into the state I need.

- Fetches the actual module via HTTP;
- Executes the same logic that my app uses;
- Relies on that store's `persist` strategy;
- Type-safe and gorgeous.
December 2, 2025 at 3:35 PM
First, don't require more than you need. It sounds obvious and yet I see this mistake everywhere. Accepting just want you need leads to versatile APIs as well as exercises your designer brain.
November 27, 2025 at 3:29 PM