Loading
Current section: Assertions 7 exercises
Problem

Asymmetric Matchers

Learn how asymmetric matchers work in Vitest and extend types so custom matchers like .toMatchSchema() are recognized by TypeScript.

Loading exercise

Transcript

00:00 Let's take a closer look at our assertion here. So we're using this custom to match schema matcher to make sure that the user object satisfies the user schema. This kind of matcher is also referred to as symmetric, because it compares one literal value, a user object, with another literal value,

00:15 the user schema. What it actually does under the hood, whether it's a strict or loose equality comparison, or some custom logic like parsing a schema, is irrelevant. What matters is that the expected value here is a literal value. That makes it symmetric. You've used plenty of

00:31 symmetric matchers before. Things like expect a string to be a string, which is also symmetric, because we're comparing one string with another string. Or even things like expect, let's say, an array of numbers to contain a particular number. This is also a symmetric matcher,

00:47 despite having nothing to do with equality. It just checks that an array contains a certain element. In contrast to symmetric matchers, there are also the asymmetric ones. Let's rewrite the same assertion using an asymmetric matcher. So here I'm comparing this literal value, my array, to be equal with the result of calling

01:10 expect.arrayContaining. Basically, comparing a literal value against the matcher result. That makes it asymmetric, because the value that we pass to this toEqual matcher is not a literal value. It's an expression. It's the result of running this array containing matcher.

01:27 So despite these two assertions being the same semantically, you can use asymmetric matchers to express much more complex logic in your tests. For example, I can say that I expect this to be an array that contains any number. In this case, any number is not a literal value by design.

01:44 So any kind of array here would pass, for example, even if I have something like 40. I can push it even further and do something like, I expect an array that has exactly three elements, and all of these elements are numbers. So in this case, this array will also pass this

02:00 assertion. One neat thing about VTest is that it will automatically make your custom matchers into both symmetric and asymmetric. So we can do something like expect user toEqual expect toMatchSchema userSchema. So these assertions are, again, the same semantically, and both of

02:19 them will work despite this being symmetric and this being asymmetric, because it compares user with the result of our custom matcher. There is another great use case for asymmetric matchers that I've prepared for you. This will be your task right now. You would have to complete an existing FetchTransaction test suite where we are validating a certain transaction object,

02:38 but nested properties of those objects would have to match our user schema. And for that, you're going to use the asymmetric variant of our custom toMatchSchema matcher. This will be an exciting one, so give it your best, and see you in a moment.