vitest-dev / vitest

Next generation testing framework powered by Vite.
https://vitest.dev
MIT License
12.19k stars 1.07k forks source link

Is it possible to add snapshots in type testing? #5857

Open MWhite-22 opened 3 weeks ago

MWhite-22 commented 3 weeks ago

Clear and concise description of the problem

Here's my scenario:

Suggested solution

So I was thinking, some type of type signature snapshot. Similar to the normal .toMatchSnapshot (or inline), but essentially we could pass in MyComponentProps and get out the whole:

type MyComponentProps = {
  variant: 'A' | 'B' | 'C';
  label: string;
  someOtherProp: any;
/// ...etc
}

It's essentially what IDE's are doing on hover when I want to inspect a type signature, but we inject it as a string snapshot for tracking and validating against unwanted changes.

Alternative

Open to any and all suggestions on how this might be possible. I have not found the right set of words to put in to google to find something that does this exact thing.

Additional context

No response

Validations

MWhite-22 commented 3 weeks ago

I've been looking through these tsc compiler API docs and I feel like this should be possible, though likely will require a lot of effort to be performant.

https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API

mrazauskas commented 3 weeks ago

Can I ask how do you write type tests for components? I am simply curious to see real world example, but that could also be helpful for someone else who is interested to implement this feature.

sheremet-va commented 1 week ago

I would also like to know the usecase so we can discuss this with the team. While it sounds useful, I am not sure it is useful.

Is it just to not bother writing the names yourself and let Vitest generate the string? (Which is a completely valid use case, current runtime snapshots are basically used because of this)

tmm commented 1 week ago

Maybe unrelated, but snapshotting compiler-related information (e.g. completions, instantiations, compiler errors) would be useful for libraries that perform a lot of type-level programming. For example, snapshotting compiler errors allows for more granular test safety than @ts-expect-error, which silences errors you might not want to.

import { expectTypeOf, test } from 'vitest'
import { mount } from './mount.js'

test('error', () => {
  // @ts-expect-error 
  expectTypeOf(mount({ name: 42 })).toHaveErrorMatchingInlineSnapshot(`Type 'number' is not assignable to type 'string'.`)
})

Also, think letting Vitest generate the strings is useful to save time for complex types!

mrazauskas commented 1 week ago

@tmm Looking at the example you provided, I think a matcher like .not.toBeCallable() or .not.toBeAssignable() would be better idea. It would make it more clear what is the intent of this test.

Similar for JSX components. I think a dedicated .toAcceptProps() matcher is a be better idea than a snapshot.

sheremet-va commented 1 week ago

I think this is more of a philosophical question. Any snapshot could've been an assertion (and probably should've), but it's easier to have an inline snapshot generated and forget about this.