🔥 (#179) Testing components is a waste of time

Hey!

I hope you're having a great week.

I tried something new recently, jumping into the world of low-code/no-code tools. I've always been a bit skeptical of them, but I had a lot fun playing around with Directus:

Quickly Build Fullstack Vue Apps with Directus

This newsletter I'm also trying something new — writing a short thing that will only appear in this email. These are ideas that aren't long enough to be a full article, but they aren't short tips either.

Let me know what you think!

And enjoy your tips.

— Michael

📝 Testing components is a waste of time

We all know that testing is a Good Thing.

It gives us confidence that our code works, makes refactoring safer and easier, and gives us early warnings if we've broken something before it hits production.

But testing Vue components can feel like a complete waste of time.

You write a test that makes sure a prop gets to the right spot, or that the right event handler is called — but maybe these tests are mostly testing Vue?

You spend ages setting up mocks for Pinia and Vue Router, just to test that one specific thing. But are you even testing your own code, or are you testing the mocks that you wrote in order to test your code?

Or maybe you avoid mocks like the plague, but you still have to provide the right test data.

And it's worse if you're using a component library that's already well tested. If the UI isn't much more than combining these components together, what are you really trying to test?

Likely, you also have some end to end tests set up.

Don't those e2e tests ultimately end up testing these components? If so, are you wasting time and effort by duplicating these tests?

What about integration tests?

Oh, and I almost forgot about Storybook and Histoire — how do these even fit in with all of this?

We need a way out of this mess. A better way to test.

To me, these are all signs that we're writing the wrong tests in the wrong way (or that our code is badly designed), not that testing itself is bad.

Testing components shouldn't be this difficult.

🔥 Default Content with Nested Slots

If you have multiple levels of nested slots, it's possible to have defaults at each level:

<!-- Parent.vue -->  <template>    <Child>      <slot>        We're in the Parent!      </slot>    </Child>  </template>
<!-- Child.vue -->  <template>    <div>      <slot>        We're in the Child!      </slot>    </div>  </template>

The slot content provided at the highest point in the hierarchy will override everything below it.

If we render Parent, it will always display We're in the Parent. But if we render just the Child component, we get We're in the Child!.

And if the component rendering the Parent component provides slot content, that will take precedence over everything:

<!-- Grandparent.vue -->  <template>    <Parent>      Haha this content rules them all!    </Parent>  </template>

🔥 Don't Override Component CSS

It can be really tempting to quickly modify a component's CSS from outside the component. If all you need is a slight modification, it seems harmless — but it's not.

Let's say you have a normally blue button, but you need it to be green in this specific case. You can override the background colour from the parent component like this:

<template>    <Button class="green">Make this button green</Button>  </template>  <style>  .green.button {    background: green;  }  </style>

This does work, but it's very fragile and prone to breaking.

What if the class name changes?

What if the HTML of the component is modified?

Anyone making changes to the button component will have no idea that this component's background colour is overridden. They won't know to update this component too.

Instead, we can just extend the functionality of the button component. That way, we keep all of the code that modifies the button inside the button component.

Here, we can add a is-green prop to the button component:

<template>    <Button is-green>Make this button green</Button>  </template>  <style>  /* No extra styles needed! */  </style>

Adding to the component itself makes it easier for anyone else who might need this button to be green in the future!

🔥 How to get rid of extra template tags

Scoped slots are lots of fun, but you have to use a lot of template tags to use them.

Luckily, a shorthand lets us get rid of it, but only if we're using a single scoped slot.

Instead of writing this:

<DataTable>    <template #header="tableAttributes">      <TableHeader v-bind="tableAttributes" />    </template>  </DataTable>

We can write this:

<DataTable #header="tableAttributes">    <TableHeader v-bind="tableAttributes" />  </DataTable>

Simple, straightforward, and marvellous.

(Ok, maybe not quite marvellous, but still pretty good)

I actually have a whole course on writing cleaner Vue code like this.

🎙️ #021 — Reactivity in Vue

Join Alex and Michael as they dive deep into Vue.js's reactivity system. They start with reactivity in Vanilla JavaScript and explore the evolution of Vue's system across versions, discussing major changes, caveats, and performance improvements. They also cover concepts like ref vs reactive, shallowRef, Vapor Mode, and more.

Watch on YouTube or listen on your favorite podcast platform.

Chapters:

In case you missed them:

📜 Effective State Management

How do we structure the state in our applications more effectively?

In this article I walk through my own thinking, introducing two new concepts to help us think about state — State Distance and State Scope.

Check it out here: Effective State Management

📜 Using Composables Well

React has hooks, Vue has composables. It's a term you maybe haven't heard before, but composables are the functions built using the composition API.

It's not an "official" term, but most of the community has settled on using this term. This is how open source works, right?

In this article, Markus goes through some common patterns for building composables with the composition API.

Check it out here: Using Composables Well

📅 Upcoming Events

Here are some upcoming events you might be interested in. Let me know if I've missed any!

PragVue 2024 — (September 17, 2024)

The first Czech Vue.js conference, taking place in Cinema City - Nový Smíchov

Check it out here

Vuejs.de Conf — (October 8, 2024 to October 9, 2024)

A community-driven Vue conference in Germany. Listen to great talks from great speakers and meet the wonderful VueJS Community.

Check it out here

Vue Fes Japan 2024 — (October 19, 2024)

Check it out here

VueConf Toronto 2024 — (November 18, 2024 to November 20, 2024)

My favourite Vue conference, in my own backyard! A three-day event with workshops, speakers from around the world, and socializing.

Check it out here

💬 Gall's Law

"A complex system that works is invariably found to have evolved from a simple system that worked. The inverse proposition also appears to be true: A complex system designed from scratch never works and cannot be made to work. You have to start over, beginning with a working simple system." — John Gall

🧠 Spaced-repetition: Mixing local and global styles together

The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬

Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.

Normally, when working with styles we want them to be scoped to a single component:

<style scoped>    .component {      background: green;    }  </style>

In a pinch though, you can also add a non-scoped style block to add in global styles if you need it:

<style>    /* Applied globally */    .component p {      margin-bottom: 16px;    }  </style>  <style scoped>    /* Scoped to this specific component */    .component {      background: green;    }  </style>

Be careful, though — global styles are dangerous and hard to track down. Sometimes, though, they're the perfect escape hatch and precisely what you need.

🔗 Want more Vue and Nuxt links?

Michael Hoffman curates a fantastic weekly newsletter with the best Vue and Nuxt links.

Sign up for it here.



p.s. I also have four products/courses: Clean Components Toolkit, Vue Tips Collection 2, Mastering Nuxt 3, and Reusable Components

Unsubscribe

评论

此博客中的热门博文

Scripting News: Tuesday, June 11, 2024

Scripting News: Tuesday, February 13, 2024