From 15d4263607b90352bb388bbeb7dd11581e3910c1 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Fri, 24 Nov 2023 11:57:56 +0000 Subject: [PATCH] Fix up document typing tests --- src/__tests__/document.test-d.ts | 303 ++++++++++++++----------------- 1 file changed, 141 insertions(+), 162 deletions(-) diff --git a/src/__tests__/document.test-d.ts b/src/__tests__/document.test-d.ts index b1b8b6b9..189b4ba3 100644 --- a/src/__tests__/document.test-d.ts +++ b/src/__tests__/document.test-d.ts @@ -1,251 +1,230 @@ -import { assertType, expectTypeOf, test } from 'vitest'; +import { expectTypeOf, test } from 'vitest'; import { Introspection } from '../introspection'; import { Document } from '../parser'; import { TypedDocument } from '../typed-document'; import { schema } from './introspection.test-d'; type Intro = Introspection; -const any = {} as any; -test('parses simple documents correctly', () => { - const query = ` +test('infers simple fields', () => { + type query = Document; - type typedDoc = TypedDocument; + `>; - const actual = any as typedDoc; + type actual = TypedDocument; + type expected = { todos: Array<{ id: string | number } | null> | null }; - assertType<{ todos: Array<{ id: string | number } | null> | null }>(actual); + expectTypeOf().toEqualTypeOf(); }); -test('parses adjacent fragments correctly', () => { - const query = ` +test('infers adjacent inline fragments', () => { + type query = Document; - type typedDoc = TypedDocument; - - const actual = any as typedDoc; + `>; - assertType<{ + type actual = TypedDocument; + type expected = { todos: Array<{ id: string | number; - text?: string | null; - complete?: boolean | null; + text: string; + complete: boolean | null; } | null> | null; - }>(actual); + }; + + expectTypeOf().toEqualTypeOf(); }); -test('parses simple documents with aliases correctly', () => { - const query = ` +test('infers aliased fields', () => { + type query = Document; - type typedDoc = TypedDocument; + `>; - const actual = any as typedDoc; + type actual = TypedDocument; + type expected = { + todos: Array<{ myIdIsGreat: string | number } | null> | null; + }; - assertType<{ todos: Array<{ myIdIsGreat: string | number } | null> | null }>(actual); + expectTypeOf().toEqualTypeOf(); }); -test('nulls when we have a skip directive', () => { - const query = ` - query { todos { id @skip(if: false) __typename @test @skip(if: false) } } - `; - type doc = Document; - type typedDoc = TypedDocument; - - const actual = any as typedDoc; +test('infers optional properties for @skip/', () => { + type query = Document; - assertType<{ + type actual = TypedDocument; + type expected = { todos: Array<{ id?: string | number; __typename?: 'Todo' } | null> | null; - }>(actual); + }; + + expectTypeOf().toEqualTypeOf(); }); -test('parses enum values', () => { - const query = ` +test('infers enum values', () => { + type query = Document; - type typedDoc = TypedDocument; + `>; - const actual = any as typedDoc; - assertType<{ + type actual = TypedDocument; + type expected = { todos: Array<{ id: string | number; test: 'value' | 'more' | null } | null> | null; - }>(actual); -}); - -test('parses inline fragments correctly', () => { - const query = ` - query { todos { ... on Todo { id text } complete } } - `; - type doc = Document; - type typedDoc = TypedDocument; - - const actual = any as typedDoc; + }; - assertType<{ - todos: Array<{ - id: string | number; - text: string | null; - complete: boolean | null; - } | null> | null; - }>(actual); + expectTypeOf().toEqualTypeOf(); }); -test('parses fragments correctly', () => { - const query = ` +test('infers fragment spreads', () => { + type query = Document; - type typedDoc = TypedDocument; - - const actual = any as typedDoc; + `>; - assertType<{ + type actual = TypedDocument; + type expected = { todos: Array<{ - id?: string | number; - text?: string | null; + __typename: 'Todo'; + id: string | number; + text: string; complete: boolean | null; - __typename?: 'Todo'; } | null> | null; - }>(actual); + }; + + expectTypeOf().toEqualTypeOf(); }); -test('mixes inline fragments and fragments correctly', () => { - const query = ` +test('infers inline fragments and fragment spreads', () => { + type query = Document; - type typedDoc = TypedDocument; + `>; - const actual = any as typedDoc; - - assertType<{ + type actual = TypedDocument; + type expected = { todos: Array<{ + __typename: 'Todo'; id: string | number; - text: string | null; + text: string; complete: boolean | null; - __typename: 'Todo'; } | null> | null; - }>(actual); + }; + + expectTypeOf().toEqualTypeOf(); }); -test('parses unions correctly', () => { - const unionQuery = ` - query { - latestTodo { +test('infers fragment spreads on unions', () => { + type query = Document; - type typedDoc = TypedDocument; - - const actual = any as typedDoc; + fragment TodoFields2 on Todo { + text + complete + __typename + } + `>; - assertType<{ + type actual = TypedDocument; + type expected = { latestTodo: - | { message: String; __typename: 'NoTodosError' } + | { message: string; __typename: 'NoTodosError' } | { - id: string | Number; - text: string | null; - complete: boolean | null; __typename: 'Todo'; + id: string | number; + text: string; + complete: boolean | null; }; - }>(actual); + }; - if (actual.latestTodo.__typename === 'NoTodosError') { - actual.latestTodo.message; - } else if (actual.latestTodo.__typename === 'Todo') { - actual.latestTodo.id; + expectTypeOf().toEqualTypeOf(); + + const data: actual = {} as any; + if (data.latestTodo.__typename === 'NoTodosError') { + data.latestTodo.message satisfies string; + } else if (data.latestTodo.__typename === 'Todo') { + data.latestTodo.id satisfies string | number; } }); -test('parses mutations correctly', () => { - const query = ` +test('infers mutations', () => { + type query = Document; - type typedDoc = TypedDocument; + `>; - const actual = any as typedDoc; - - assertType<{ + type actual = TypedDocument; + type expected = { toggleTodo: { id: string | number } | null; - }>(actual); + }; + + expectTypeOf().toEqualTypeOf(); }); -test('parses unions with interfaces correctly', () => { - const unionQuery = ` - query { - test { +test('infers unions and interfaces correctly', () => { + type query = Document; - type typedDoc = TypedDocument; + `>; - const actual = any as typedDoc; - - assertType<{ + type actual = TypedDocument; + type expected = { test: | { - id: string | Number; - text: string | null; - maxLength: number | null; __typename: 'SmallTodo'; + id: string | number; + text: string; + maxLength: number | null; + } + | { + __typename: 'BigTodo'; + id: string | number; + wallOfText: string | null; } - | { id: string | Number; wallOfText: string | null; __typename: 'BigTodo' } | null; - }>(actual); + }; + + expectTypeOf().toEqualTypeOf(); }); -test('parses GitHub queries correctly', () => { - const repositories = /* GraphQL */ ` +test('infers queries from GitHub Introspection schema', () => { + type githubIntrospection = import('./fixtures/githubIntrospection').GitHubIntrospection; + + type repositories = Document; - type githubIntrospection = import('./fixtures/githubIntrospection').GitHubIntrospection; - type doc = Document; - type actual = TypedDocument; + type actual = TypedDocument; type expected = { repository: {