Vitest and the future of testing

Issue #307.July 18, 2024.2 Minute read.
Bytes

Today’s issue: Astro’s new situationship, programming your own nostalgia machine, and what Hono has in common with my Temu blender.

Welcome to #307.


Eyeballs logo

The Main Thing

A guy dressed up as a cone sitting next to a bunch of real cones

The one component you "forgot" to test

Vitest and the future of testing

As someone who (allegedly) doesn’t write any tests, I might not seem like the most qualified person to write about last week’s Vitest 2.0 release. But if I’ve learned anything from watching Bronny James play basketball, it’s that being “qualified” for your job is overrated – so let’s strap in.

Quick review: Vitest has quietly become the fastest-growing test framework in the JavaScript ecosystem for the past couple years, racking up 5 million downloads a week. It definitely helps to be the default test runner for Vite, but it’s more than just a nepo baby. With Vitest, you get a more modern version of Jest that’s faster, easier to configure, and uses the same Jest API you already know and love.

Vitest 2.0 continues to build on that success with a major new feature called Browser Mode, which is Vitest’s take on component testing with a few interesting twists:

  • No more “fake DOM” – Browser Mode is built on top of Playwright and renders components inside an iframe, using real browser events to test your code. This makes your component tests more accurate and less error-prone than JSDOM and snapshot testing.

  • Unified tooling – Before Vitest, component testing required you to create separate configurations for Jest, Storybook, and Webpack. Now, you can leverage the same config used to bundle your app to run your unit and component tests.

  • A new sweet spot – There’s historically been a missing middle ground between unit tests and end-to-end tests. Browser Mode might be the missing ingredient that makes component tests useful enough to actually invest in going forward.

Bottom Line: It’s a Vite world, and we’re all just living in it.

        

Stackblitz logo

Our Friends
(With Benefits)

Sully from Monsters Inc holding up 5 stars

When you find a design system that's actually up to date

StackBlitz is a design system cheat code

How would you rate your team’s design systems?

I’m guessing it’s somewhere between “jumbled mess” and “woefully out of date ever since Doug quit 2 years ago.”

That’s why smart teams (like Google!) are using StackBlitz’s browser-based dev environment to build next-gen design systems that are incredibly easy to use and maintain:

  • Provide live, interactive documentation with one-click instant environments – so your team can easily try out internal libraries

  • Share complete environments with just a URL – so you can get one-click bug reproductions with no local installations

  • Build and update static sites without a dev server – so anyone on your team can easily contribute to your docs

Google DevRel Lead, Stephen Fluin says that “for frameworks & design systems to succeed, they have to be incredibly easy to adopt. Setting up local environments is one of the biggest barriers.”

Check out StackBlitz for free to instantly remove that barrier for your team.


Spot the Bug logo

Spot the Bug

Presented by React Rally

One of the most loved React conferences is happening in Park City, Utah on Aug 12-14, and they’re offering a 25% discount to all Bytes subscribers. Don’t miss it.

<html lang="en">
  <input type="checkbox" id="checkbox" />
  <label for="checkbox">Click me</label>
  <p id="message"></p>

  <script>
    checkbox.onclick = () => handleClick();

    function handleClick() {
      if (checkbox.checked) {
        message.textContent = "Checkbox is checked!";
        return true;
      } else {
        message.textContent = "Checkbox is unchecked!";
        return false;
      }
    }
  </script>
</html>

Cool Bits logo

Cool Bits

  1. Hono released v4.5, adding React 19 support and 3 new middlewares, giving it 20 in total now. That’s almost half the number of built-in features that came with the wifi-enabled blender I bought off Temu for $4.

  2. James Cowling wrote a deep dive about how he and his team built a new feature that lets you programmatically generate cron jobs via a new Convex helper. [sponsored]

  3. You’ll be able to animate height: auto in Chrome 128. I never thought I’d live to see this day 🥹.

  4. You can get your very own Bytes-themed ticket to ViteConf this year, because it was the only way they could get us to stop making “Feet Conf” jokes.

  5. Temani Afif wrote a CSS Tip about how to get the screen width and height without using JavaScript.

  6. Karthikeya launched Eldora UI, an animated UI library built with React, Typescript, Tailwind CSS, and Framer Motion.

  7. Zed (the next-gen code editor created by the same folks that made Atom) just added support for Linux, which is exciting news for the Kernel Mafia members among us.

  8. Netlify is partnering with Astro to become their “Official Deployment Partner.” Love wins.

  9. Rodrigo Pombo wrote about using fine-grained markdown with Code Hike and showed how it works throughout the article.

  10. Alexander Keliris wrote about how to create the THX Deep Note™️ using JavaScript. You should know that it’s physiologically impossible to listen to this sound without feeling a burning desire to rewatch Return of the Jedi.


Spot the Bug logo

Spot the Bug: Solution

Returning false from the event handler disables the default action of the checkbox. This means that the checkbox will not change its state when clicked. You can use the void operator to prevent the return value from interfering with the default action:

<html lang="en">
  <input type="checkbox" id="checkbox" />
  <label for="checkbox">Click me</label>
  <p id="message"></p>

  <script>
    checkbox.onclick = () => void handleClick();

    function handleClick() {
      if (checkbox.checked) {
        message.textContent = "Checkbox is checked!";
        return true;
      } else {
        message.textContent = "Checkbox is unchecked!";
        return false;
      }
    }
  </script>
</html>